FairRoot
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MCStepLoggerImpl.cxx
Go to the documentation of this file.
1 // Copyright CERN and copyright holders of ALICE O2. This software is
2 // distributed under the terms of the GNU General Public License v3 (GPL
3 // Version 3), copied verbatim in the file "COPYING".
4 //
5 // See https://alice-o2.web.cern.ch/ for full licensing information.
6 //
7 // In applying this license CERN does not waive the privileges and immunities
8 // granted to it by virtue of its status as an Intergovernmental Organization
9 // or submit itself to any jurisdiction.
10 
11 //****************************************************************************
12 //* This file is free software: you can redistribute it and/or modify *
13 //* it under the terms of the GNU General Public License as published by *
14 //* the Free Software Foundation, either version 3 of the License, or *
15 //* (at your option) any later version. *
16 //* *
17 //* Primary Authors: Sandro Wenzel <sandro.wenzel@cern.ch> *
18 //* *
19 //* The authors make no claims about the suitability of this software for *
20 //* any purpose. It is provided "as is" without express or implied warranty. *
21 //****************************************************************************
22 
23 // @file MCStepLoggerImpl.cxx
24 // @author Sandro Wenzel
25 // @since 2017-06-29
26 // @brief A logging service for MCSteps (hooking into Stepping of FairMCApplication's)
27 // @author Radoslaw Karabowicz
28 // @since 2018-10-22
29 // @brief Modified for FairRoot
30 
31 #include <FairMCApplication.h>
32 #include <TAxis.h> // for TAxis
33 #include <TFile.h> // for TAxis
34 #include <TH1.h> // for TH1F
35 #include <TTree.h>
36 #include <TVirtualMC.h>
37 #include <TVirtualMCStack.h> // for TVirtualMCStack
38 #include <cassert>
39 #include <dlfcn.h>
40 #include <iostream>
41 #include <map>
42 #include <set>
43 #include <sstream>
44 #include <utility> // for pair
45 #ifdef NDEBUG
46 #undef NDEBUG
47 #endif
48 
50 {
51  int stepcounter = 0;
52 
53  std::set<int> trackset;
54  std::set<int> pdgset;
55  std::map<int, int> volumetosteps;
56  std::map<int, int> volumetostepsGlobal;
57  std::map<int, char const*> idtovolname;
58 
59  // TODO: consider writing to a TTree/TFile
60  public:
61  void addStep(TVirtualMC* mc)
62  {
63  assert(mc);
64  stepcounter++;
65  auto stack = mc->GetStack();
66  assert(stack);
67  trackset.insert(stack->GetCurrentTrackNumber());
68  pdgset.insert(mc->TrackPid());
69  int copyNo;
70  auto id = mc->CurrentVolID(copyNo);
71  if (volumetosteps.find(id) == volumetosteps.end()) {
72  volumetosteps.insert(std::pair<int, int>(id, 0));
73  } else {
74  volumetosteps[id]++;
75  }
76  if (volumetostepsGlobal.find(id) == volumetostepsGlobal.end()) {
77  volumetostepsGlobal.insert(std::pair<int, int>(id, 0));
78  } else {
79  volumetostepsGlobal[id]++;
80  }
81  if (idtovolname.find(id) == idtovolname.end()) {
82  idtovolname.insert(std::pair<int, char const*>(id, mc->CurrentVolName()));
83  }
84  }
85 
86  void clear()
87  {
88  stepcounter = 0;
89  trackset.clear();
90  pdgset.clear();
91  volumetosteps.clear();
92  }
93 
94  void flush()
95  {
96  std::cerr << "did " << stepcounter << " steps \n";
97  std::cerr << "transported " << trackset.size() << " different tracks \n";
98  std::cerr << "transported " << pdgset.size() << " different types \n";
99  // summarize steps per volume
100  for (auto& p : volumetosteps) {
101  std::cout << " VolName " << idtovolname[p.first] << " COUNT " << p.second << "\n";
102  }
103  clear();
104  }
105 
106  void flushFinal()
107  {
108  // summarize steps per volume
109  TFile* stepLoggerFile = TFile::Open("stepLogger.root", "recreate");
110  TH1F* stepLoggerHistogram = new TH1F("stepLoggerHistogram",
111  "Step logger results;volume number;number of steps",
112  volumetostepsGlobal.size(),
113  0.5,
114  volumetostepsGlobal.size() + 0.5);
115  uint binNumber = 0;
116  for (auto& p : volumetostepsGlobal) {
117  std::cout << " VolName " << idtovolname[p.first] << " COUNT " << p.second << "\n";
118  stepLoggerHistogram->SetBinContent(++binNumber, p.second);
119  stepLoggerHistogram->GetXaxis()->SetBinLabel(binNumber, idtovolname[p.first]);
120  }
121  stepLoggerHistogram->DrawClone();
122  stepLoggerFile->Write();
123  stepLoggerFile->Close();
124  }
125 };
126 
128 
129 // a generic function that can dispatch to the original method of a FairMCApplication
130 // (for functions of type void FairMCApplication::Method(void); )
131 // RK: did two versions, because on the first call while Stepping the origMethod was set to avoid calling it over and
132 // over again RK: but this setting also prevented the FinishEvent ever be calling - instead Stepping was also called
133 extern "C" void dispatchStepping(FairMCApplication* app, char const* libname, char const* origFunctionName)
134 {
135  typedef void (FairMCApplication::*StepMethodType)();
136  static StepMethodType origMethod = nullptr;
137  if (origMethod == nullptr) {
138  auto libHandle = dlopen(libname, RTLD_NOW);
139  // try to make the library loading a bit more portable:
140  if (!libHandle) {
141  // try appending *.so
142  std::stringstream stream;
143  stream << libname << ".so";
144  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
145  }
146  if (!libHandle) {
147  // try appending *.dylib
148  std::stringstream stream;
149  stream << libname << ".dylib";
150  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
151  }
152  assert(libHandle);
153  void* symbolAddress = dlsym(libHandle, origFunctionName);
154  assert(symbolAddress);
155  // hack since C++ does not allow casting to C++ member function pointers
156  // thanks to gist.github.com/mooware/1174572
157  memcpy(&origMethod, &symbolAddress, sizeof(symbolAddress));
158  }
159  (app->*origMethod)();
160 }
161 
162 // a generic function that can dispatch to the original method of a FairMCApplication
163 // (for functions of type void FairMCApplication::Method(void); )
164 // RK: did two versions, because on the first call while Stepping the origMethod was set to avoid calling it over and
165 // over again RK: but this setting also prevented the FinishEvent ever be calling - instead Stepping was also called
166 extern "C" void dispatchFinishEvent(FairMCApplication* app, char const* libname, char const* origFunctionName)
167 {
168  typedef void (FairMCApplication::*StepMethodType)();
169  static StepMethodType origMethod = nullptr;
170  if (origMethod == nullptr) {
171  auto libHandle = dlopen(libname, RTLD_NOW);
172  // try to make the library loading a bit more portable:
173  if (!libHandle) {
174  // try appending *.so
175  std::stringstream stream;
176  stream << libname << ".so";
177  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
178  }
179  if (!libHandle) {
180  // try appending *.dylib
181  std::stringstream stream;
182  stream << libname << ".dylib";
183  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
184  }
185  assert(libHandle);
186  void* symbolAddress = dlsym(libHandle, origFunctionName);
187  assert(symbolAddress);
188  // hack since C++ does not allow casting to C++ member function pointers
189  // thanks to gist.github.com/mooware/1174572
190  memcpy(&origMethod, &symbolAddress, sizeof(symbolAddress));
191  }
192  (app->*origMethod)();
193 }
194 
195 // a generic function that can dispatch to the original method of a FairMCApplication
196 // (for functions of type void FairMCApplication::Method(void); )
197 // RK: did two versions, because on the first call while Stepping the origMethod was set to avoid calling it over and
198 // over again RK: but this setting also prevented the FinishEvent ever be calling - instead Stepping was also called
199 extern "C" void dispatchFinishRun(FairMCApplication* app, char const* libname, char const* origFunctionName)
200 {
201  typedef void (FairMCApplication::*StepMethodType)();
202  static StepMethodType origMethod = nullptr;
203  if (origMethod == nullptr) {
204  auto libHandle = dlopen(libname, RTLD_NOW);
205  // try to make the library loading a bit more portable:
206  if (!libHandle) {
207  // try appending *.so
208  std::stringstream stream;
209  stream << libname << ".so";
210  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
211  }
212  if (!libHandle) {
213  // try appending *.dylib
214  std::stringstream stream;
215  stream << libname << ".dylib";
216  libHandle = dlopen(stream.str().c_str(), RTLD_NOW);
217  }
218  assert(libHandle);
219  void* symbolAddress = dlsym(libHandle, origFunctionName);
220  assert(symbolAddress);
221  // hack since C++ does not allow casting to C++ member function pointers
222  // thanks to gist.github.com/mooware/1174572
223  memcpy(&origMethod, &symbolAddress, sizeof(symbolAddress));
224  }
225  (app->*origMethod)();
226 }
227 
228 extern "C" void performLogging(FairMCApplication* app)
229 {
230  static TVirtualMC* mc = TVirtualMC::GetMC();
231  logger.addStep(mc);
232 }
233 
234 extern "C" void flushLog() { logger.flush(); }
235 
236 extern "C" void flushFinalLog() { logger.flushFinal(); }
void addStep(TVirtualMC *mc)
void dispatchFinishEvent(FairMCApplication *, char const *libname, char const *)
void dispatchStepping(FairMCApplication *, char const *libname, char const *)
void flushLog()
void flushFinalLog()
void dispatchFinishRun(FairMCApplication *, char const *libname, char const *)
StepLogger logger
void performLogging(FairMCApplication *)