16 #include <arich/modules/arichToNtuple/arichToNtupleModule.h>
18 #include <arich/dataobjects/ARICHLikelihood.h>
19 #include <arich/dataobjects/ARICHAeroHit.h>
20 #include <arich/dataobjects/ARICHTrack.h>
21 #include <arich/dataobjects/ARICHPhoton.h>
22 #include <arich/dataobjects/ARICHHit.h>
23 #include <mdst/dataobjects/Track.h>
24 #include <tracking/dataobjects/ExtHit.h>
27 #include <analysis/dataobjects/ParticleList.h>
28 #include <analysis/VariableManager/Manager.h>
29 #include <analysis/VariableManager/Utility.h>
32 #include <framework/logging/Logger.h>
33 #include <framework/pcore/ProcHandler.h>
34 #include <framework/core/ModuleParam.templateDetails.h>
36 #include <framework/datastore/DataStore.h>
37 #include <framework/datastore/StoreArray.h>
40 #include <framework/utilities/MakeROOTCompatible.h>
41 #include <framework/utilities/RootFileCreationManager.h>
56 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.");
57 setPropertyFlags(c_ParallelProcessingCertified | c_TerminateInAllProcesses);
59 vector<string> emptylist;
60 addParam(
"particleList", m_particleList,
61 "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)",
63 addParam(
"arichSelector", m_arichSelector,
64 "Decay string with selected particles to which arich info should be appened", std::string(
""));
65 addParam(
"variables", m_variables,
66 "List of variables (or collections) to save. Variables are taken from Variable::Manager, and are identical to those available to e.g. ParticleSelector.",
68 addParam(
"arichVariables", m_arichVariables,
69 "List of aliases for particles to which arich info will be appended (used for tree branch names)",
72 addParam(
"fileName", m_fileName,
"Name of ROOT file for output.",
string(
"arichToNtuple.root"));
73 addParam(
"treeName", m_treeName,
"Name of the NTuple in the saved file.",
string(
"ntuple"));
75 std::tuple<std::string, std::map<int, unsigned int>> default_sampling{
"", {}};
76 addParam(
"sampling", m_sampling,
77 "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.",
81 void arichToNtupleModule::initialize()
83 m_eventMetaData.isRequired();
90 arichTracks.isRequired();
93 if (not m_particleList.empty())
96 m_decaydescriptor.init(m_arichSelector);
99 if (m_fileName.empty()) {
100 B2FATAL(
"Output root file name is not set. Please set a vaild root output file name (\"fileName\" module parameter).");
104 m_file = RootFileCreationManager::getInstance().getFile(m_fileName);
106 B2ERROR(
"Could not create file \"" << m_fileName <<
107 "\". Please set a vaild root output file name (\"fileName\" module parameter).");
111 TDirectory::TContext directoryGuard(m_file.get());
114 if (m_file->Get(m_treeName.c_str())) {
115 B2FATAL(
"Tree with the name \"" << m_treeName
116 <<
"\" already exists in the file \"" << m_fileName <<
"\"\n"
117 <<
"\nYou probably want to either set the output fileName or the treeName to something else:\n\n"
118 <<
" from modularAnalysis import arichToNtuple\n"
119 <<
" arichToNtuple('pi+:all', ['p'], treename='pions', filename='arichToNtuple.root')\n"
120 <<
" arichToNtuple('gamma:all', ['p'], treename='photons', filename='arichToNtuple.root') # two trees, same file\n"
122 <<
" from modularAnalysis import arichToNtuple\n"
123 <<
" arichToNtuple('pi+:all', ['p'], filename='pions.root')\n"
124 <<
" arichToNtuple('gamma:all', ['p'], filename='photons.root') # two files\n"
130 m_tree.registerInDataStore(m_fileName + m_treeName, DataStore::c_DontWriteOut);
131 m_tree.construct(m_treeName.c_str(),
"");
132 m_tree->get().SetCacheSize(100000);
135 m_tree->get().Branch(
"__experiment__", &m_experiment,
"__experiment__/I");
136 m_tree->get().Branch(
"__run__", &m_run,
"__run__/I");
137 m_tree->get().Branch(
"__event__", &m_event,
"__event__/I");
138 if (not m_particleList.empty()) {
139 m_tree->get().Branch(
"__candidate__", &m_candidate,
"__candidate__/I");
140 m_tree->get().Branch(
"__ncandidates__", &m_ncandidates,
"__ncandidates__/I");
142 for (
const auto& variable : m_variables)
143 if (Variable::isCounterVariable(variable)) {
144 B2WARNING(
"The counter '" << variable
145 <<
"' is handled automatically by arichToNtuple, you don't need to add it.");
149 m_variables = Variable::Manager::Instance().resolveCollections(m_variables);
150 m_branchAddresses.resize(m_variables.size() + 1);
151 m_tree->get().Branch(
"__weight__", &m_branchAddresses[0],
"__weight__/D");
152 size_t enumerate = 1;
153 for (
const string& varStr : m_variables) {
156 m_tree->get().Branch(branchName.c_str(), &m_branchAddresses[enumerate], (branchName +
"/D").c_str());
161 B2ERROR(
"Variable '" << varStr <<
"' is not available in Variable::Manager!");
163 m_functions.push_back(var->function);
169 for (
const string& varStr : m_arichVariables) {
171 addARICHBranches(branchName);
174 m_tree->get().SetBasketSize(
"*", 1600);
176 m_sampling_name = std::get<0>(m_sampling);
177 m_sampling_rates = std::get<1>(m_sampling);
179 if (m_sampling_name !=
"") {
180 m_sampling_variable = Variable::Manager::Instance().getVariable(m_sampling_name);
181 if (m_sampling_variable ==
nullptr) {
182 B2FATAL(
"Couldn't find sample variable " << m_sampling_name <<
" via the Variable::Manager. Check the name!");
184 for (
const auto& pair : m_sampling_rates)
185 m_sampling_counts[pair.first] = 0;
187 m_sampling_variable =
nullptr;
192 float arichToNtupleModule::getInverseSamplingRateWeight(
const Particle* particle)
194 if (m_sampling_variable ==
nullptr)
197 long target = std::lround(m_sampling_variable->function(particle));
198 if (m_sampling_rates.find(target) != m_sampling_rates.end() and m_sampling_rates[target] > 0) {
199 m_sampling_counts[target]++;
200 if (m_sampling_counts[target] % m_sampling_rates[target] != 0)
203 m_sampling_counts[target] = 0;
204 return m_sampling_rates[target];
210 void arichToNtupleModule::event()
212 m_event = m_eventMetaData->getEvent();
213 m_run = m_eventMetaData->getRun();
214 m_experiment = m_eventMetaData->getExperiment();
216 if (m_particleList.empty()) {
217 m_branchAddresses[0] = getInverseSamplingRateWeight(
nullptr);
218 if (m_branchAddresses[0] > 0) {
219 for (
unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
220 m_branchAddresses[iVar + 1] = m_functions[iVar](
nullptr);
222 for (
auto& arich : m_arich) arich->clear();
223 m_tree->get().Fill();
228 m_ncandidates = particlelist->getListSize();
230 for (
unsigned int iPart = 0; iPart < m_ncandidates; iPart++) {
232 const Particle* particle = particlelist->getParticle(iPart);
233 m_branchAddresses[0] = getInverseSamplingRateWeight(particle);
234 if (m_branchAddresses[0] > 0) {
235 for (
unsigned int iVar = 0; iVar < m_variables.size(); iVar++) {
236 m_branchAddresses[iVar + 1] = m_functions[iVar](particle);
238 for (
auto& arich : m_arich) arich->clear();
239 fillARICHTree(particle);
240 m_tree->get().Fill();
246 void arichToNtupleModule::terminate()
248 if (!ProcHandler::parallelProcessingUsed() or ProcHandler::isOutputProcess()) {
249 B2INFO(
"Writing NTuple " << m_treeName);
250 TDirectory::TContext directoryGuard(m_file.get());
251 m_tree->write(m_file.get());
253 const bool writeError = m_file->TestBit(TFile::kWriteError);
256 B2FATAL(
"A write error occured while saving '" << m_fileName <<
"', please check if enough disk space is available.");
261 void arichToNtupleModule::addARICHBranches(
const std::string& name)
265 m_arich.push_back(tree);
266 m_tree->get().Branch((name +
"_detPhot").c_str(), &tree->detPhot,
"detPhot/I");
267 m_tree->get().Branch((name +
"_expPhot").c_str(), &tree->expPhot,
"e/F:mu:pi:K:p:d");
268 m_tree->get().Branch((name +
"_logL").c_str(), &tree->logL,
"e/F:mu:pi:K:p:d");
269 m_tree->get().Branch((name +
"_recHit").c_str(), &tree->recHit,
"PDG/I:x/F:y:z:p:theta:phi");
270 m_tree->get().Branch((name +
"_mcHit").c_str(), &tree->mcHit,
"PDG/I:x/F:y:z:p:theta:phi");
271 m_tree->get().Branch((name +
"_winHit").c_str(), &tree->winHit,
"x/F:y");
272 m_tree->get().Branch((name +
"_photons").c_str(),
"std::vector<Belle2::ARICHPhoton>", &tree->photons);
276 void arichToNtupleModule::fillARICHTree(
const Particle* particle)
279 std::vector<const Particle*> selParticles = m_decaydescriptor.getSelectionParticles(particle);
281 for (
auto p : selParticles) {
282 const Track* track = p->getTrack();
283 if (!track)
continue;
284 for (
const ExtHit& hit : track->getRelationsTo<
ExtHit>()) {
290 m_arich[iTree]->winHit[0] = winHit.X();
291 m_arich[iTree]->winHit[1] = winHit.Y();
297 m_arich[iTree]->recHit.x = recPos.X();
298 m_arich[iTree]->recHit.y = recPos.Y();
299 m_arich[iTree]->recHit.z = recPos.Z();
302 m_arich[iTree]->recHit.p = recMom.Mag();
303 m_arich[iTree]->recHit.theta = recMom.Theta();
304 m_arich[iTree]->recHit.phi = recMom.Phi();
309 m_arich[iTree]->logL.e = lkh->
getLogL(Const::electron);
310 m_arich[iTree]->logL.mu = lkh->
getLogL(Const::muon);
311 m_arich[iTree]->logL.pi = lkh->
getLogL(Const::pion);
312 m_arich[iTree]->logL.K = lkh->
getLogL(Const::kaon);
313 m_arich[iTree]->logL.p = lkh->
getLogL(Const::proton);
314 m_arich[iTree]->logL.d = lkh->
getLogL(Const::deuteron);
316 m_arich[iTree]->expPhot.e = lkh->
getExpPhot(Const::electron);
317 m_arich[iTree]->expPhot.mu = lkh->
getExpPhot(Const::muon);
318 m_arich[iTree]->expPhot.pi = lkh->
getExpPhot(Const::pion);
319 m_arich[iTree]->expPhot.K = lkh->
getExpPhot(Const::kaon);
320 m_arich[iTree]->expPhot.p = lkh->
getExpPhot(Const::proton);
321 m_arich[iTree]->expPhot.d = lkh->
getExpPhot(Const::deuteron);
329 m_arich[iTree]->mcHit.x = truePos.X();
330 m_arich[iTree]->mcHit.y = truePos.Y();
331 m_arich[iTree]->mcHit.z = truePos.Z();
334 m_arich[iTree]->mcHit.p = trueMom.Mag();
335 m_arich[iTree]->mcHit.theta = trueMom.Theta();
336 m_arich[iTree]->mcHit.phi = trueMom.Phi();
337 m_arich[iTree]->mcHit.PDG = aeroHit->
getPDG();