Belle II Software  release-08-01-10
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 
38 using namespace Belle2;
39 
40 // Register module in the framework
41 REG_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
122  m_tree.registerInDataStore(m_fileName + m_treeName, DataStore::c_DontWriteOut);
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 
272 void arichToNtupleModule::addARICHBranches(const std::string& name)
273 {
274 
275  ARICH::ARICHTree* tree = new ARICH::ARICHTree();
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  TVector2 winHit = atrk->windowHitPosition();
301  m_arich[iTree]->winHit[0] = winHit.X();
302  m_arich[iTree]->winHit[1] = winHit.Y();
303  }
304 
305  m_arich[iTree]->photons = atrk->getPhotons();
306 
307  TVector3 recPos = atrk->getPosition();
308  m_arich[iTree]->recHit.x = recPos.X();
309  m_arich[iTree]->recHit.y = recPos.Y();
310  m_arich[iTree]->recHit.z = recPos.Z();
311 
312  TVector3 recMom = atrk->getDirection() * atrk->getMomentum();
313  m_arich[iTree]->recHit.p = recMom.Mag();
314  m_arich[iTree]->recHit.theta = recMom.Theta();
315  m_arich[iTree]->recHit.phi = recMom.Phi();
316 
317  const ARICHLikelihood* lkh = NULL;
318  lkh = track->getRelated<ARICHLikelihood>();
319  if (lkh) {
320  m_arich[iTree]->logL.e = lkh->getLogL(Const::electron);
321  m_arich[iTree]->logL.mu = lkh->getLogL(Const::muon);
322  m_arich[iTree]->logL.pi = lkh->getLogL(Const::pion);
323  m_arich[iTree]->logL.K = lkh->getLogL(Const::kaon);
324  m_arich[iTree]->logL.p = lkh->getLogL(Const::proton);
325  m_arich[iTree]->logL.d = lkh->getLogL(Const::deuteron);
326 
327  m_arich[iTree]->expPhot.e = lkh->getExpPhot(Const::electron);
328  m_arich[iTree]->expPhot.mu = lkh->getExpPhot(Const::muon);
329  m_arich[iTree]->expPhot.pi = lkh->getExpPhot(Const::pion);
330  m_arich[iTree]->expPhot.K = lkh->getExpPhot(Const::kaon);
331  m_arich[iTree]->expPhot.p = lkh->getExpPhot(Const::proton);
332  m_arich[iTree]->expPhot.d = lkh->getExpPhot(Const::deuteron);
333 
334  m_arich[iTree]->detPhot = lkh->getDetPhot();
335  }
336 
337  const ARICHAeroHit* aeroHit = atrk->getRelated<ARICHAeroHit>();
338  if (aeroHit) {
339  TVector3 truePos = aeroHit->getPosition();
340  m_arich[iTree]->mcHit.x = truePos.X();
341  m_arich[iTree]->mcHit.y = truePos.Y();
342  m_arich[iTree]->mcHit.z = truePos.Z();
343 
344  TVector3 trueMom = aeroHit->getMomentum();
345  m_arich[iTree]->mcHit.p = trueMom.Mag();
346  m_arich[iTree]->mcHit.theta = trueMom.Theta();
347  m_arich[iTree]->mcHit.phi = trueMom.Phi();
348  m_arich[iTree]->mcHit.PDG = aeroHit->getPDG();
349 
350  }
351  }
352  iTree++;
353  }
354 }
Datastore class that holds information on track parameters at the entrance in aerogel.
Definition: ARICHAeroHit.h:27
TVector3 getMomentum() const
Get track momentum (at entrance in 1. aerogel plane)
Definition: ARICHAeroHit.h:71
int getPDG() const
Get particle PDG identity number.
Definition: ARICHAeroHit.h:65
TVector3 getPosition() const
Get track position (at entrance in 1. aerogel plane)
Definition: ARICHAeroHit.h:68
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:32
const std::vector< ARICHPhoton > & getPhotons() const
Returns vector of ARICHPhoton's associated with track.
Definition: ARICHTrack.h:189
bool hitsWindow() const
Returns true if track hits HAPD window.
Definition: ARICHTrack.h:151
TVector3 getPosition() const
returns track position vector
Definition: ARICHTrack.h:133
TVector2 windowHitPosition() const
Get HAPD window hit position.
Definition: ARICHTrack.h:157
TVector3 getDirection() const
returns track direction vector
Definition: ARICHTrack.h:139
double getMomentum() const
returns track momentum
Definition: ARICHTrack.h:145
static const ChargedStable muon
muon particle
Definition: Const.h:651
static const ChargedStable pion
charged pion particle
Definition: Const.h:652
static const ChargedStable proton
proton particle
Definition: Const.h:654
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:653
static const ChargedStable electron
electron particle
Definition: Const.h:650
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:655
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:32
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
REG_MODULE(arichBtest)
Register the Module.
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.
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