BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
FileMapper.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "FileMapper.hh"
20#include "Header.hh"
21#include "HistogramAccumulator.hh"
22#include "HistogramAccumulatorMerge.hh"
23#include "HistogramAccumulatorSum.hh"
24
25#include "BDSOutputROOTEventHeader.hh"
26
27#include "TDirectory.h"
28#include "TFile.h"
29#include "TH1.h"
30#include "TH1D.h"
31#include "TH2D.h"
32#include "TH3D.h"
33#include "TList.h"
34#include "TKey.h"
35#include "TObject.h"
36#include "TTree.h"
37
38#include <algorithm>
39#include <iostream>
40#include <string>
41#include <vector>
42
43
44bool RBDS::GetFileType(TFile* file,
45 std::string& fileType,
46 int* dataVersion)
47{
48 // check if valid file at all
49 if (file->IsZombie())
50 {return false;}
51
52 // load header to get which type of file it is
53 TTree* headerTree = dynamic_cast<TTree*>(file->Get("Header"));
54 if (!headerTree)
55 {return false;} // no header -> definitely not a bdsim file
56 Header* headerLocal = new Header();
57 headerLocal->SetBranchAddress(headerTree);
58 headerTree->GetEntry(0);
59 fileType = headerLocal->header->fileType;
60 if (dataVersion) // optional
61 {(*dataVersion) = headerLocal->header->dataVersion;}
62 delete headerLocal;
63 return true;
64}
65
66bool RBDS::IsBDSIMOutputFile(TFile* file,
67 int* dataVersion)
68{
69 if (!file)
70 {return false;}
71 // check if valid file at all
72 if (file->IsZombie())
73 {return false;}
74
75 std::string fileType;
76 bool success = GetFileType(file, fileType, dataVersion);
77 if (!success)
78 {return false;}
79
80 return fileType == "BDSIM";
81}
82
83bool RBDS::IsBDSIMOutputFile(const std::string& filePath,
84 int* dataVersion)
85{
86 TFile* f = new TFile(filePath.c_str());
87 bool result = IsBDSIMOutputFile(f, dataVersion);
88 f->Close();
89 delete f;
90 return result;
91}
92
94{
95 // check if valid file at all
96 if (file->IsZombie())
97 {return false;}
98
99 std::string fileType;
100 bool success = GetFileType(file, fileType);
101 if (!success)
102 {return false;}
103
104 return fileType == "REBDSIM";
105}
106
107bool RBDS::IsREBDSIMOutputFile(const std::string& filePath)
108{
109 TFile* f = new TFile(filePath.c_str());
110 bool result = IsREBDSIMOutputFile(f);
111 f->Close();
112 delete f;
113 return result;
114}
115
117{
118 // check if valid file at all
119 if (file->IsZombie())
120 {return false;}
121
122 std::string fileType;
123 bool success = GetFileType(file, fileType);
124 if (!success)
125 {return false;}
126
127 // check if 'REBDSIM' is in the name at all
128 // 'REBDSIM' or 'REBDSIMCOMBINE' are possible options
129 std::size_t found = fileType.find("REBDSIM");
130 return found != std::string::npos;
131}
132
133bool RBDS::IsREBDSIMOrCombineOutputFile(const std::string& filePath)
134{
135 TFile* f = new TFile(filePath.c_str());
136 bool result = IsREBDSIMOrCombineOutputFile(f);
137 f->Close();
138 delete f;
139 return result;
140}
141
143{
144 return (int)h->GetDimension();
145}
146
147void RBDS::WarningMissingHistogram(const std::string& histName,
148 const std::string& fileName)
149{
150 std::cout << "No histogram \"" << histName << "\" in file " << fileName << std::endl;
151}
152
154 TFile* output,
155 bool debugIn):
156 debug(debugIn)
157{
158 TDirectory* rootDir = static_cast<TDirectory*>(file);
159
160 std::string rootDirName = "";
161 MapDirectory(rootDir, output, rootDirName);
162}
163
164void HistogramMap::MapDirectory(TDirectory* dir,
165 TFile* output,
166 const std::string& dirPath)
167{
168 // to safely return to where we were and not affect other code
169 // cache the current directory
170 TDirectory* originalDir = TDirectory::CurrentDirectory();
171 if (debug)
172 {
173 gDirectory->pwd();
174 std::cout << "Original directory: " << originalDir->GetName() << std::endl;
175 std::cout << "Directory: " << dir->GetName() << std::endl;
176 }
177 dir->cd(); // change into dir
178
179 if (debug)
180 {gDirectory->pwd();}
181
182 TList* dirk = dir->GetListOfKeys();
183 for (int i = 0; i < dirk->GetEntries(); ++i)
184 {
185 TObject* keyObject = dirk->At(i); // key object in list of keys
186 TObject* dirObject = dir->Get(keyObject->GetName()); // object in file
187
188 std::string objectName = std::string(keyObject->GetName());
189 std::string className = std::string(dirObject->ClassName());
190
191 if (className == "TDirectory" || className == "TDirectoryFile")
192 {
193 TDirectory* subDir = dynamic_cast<TDirectory*>(dirObject);
194 if (!subDir)
195 {continue;} // shouldn't happen but protect against bad dynamic cast access
196 MapDirectory(subDir, output, dirPath + "/" + objectName); // recursion!
197 }
198 else if (dirObject->InheritsFrom("TH1") || dirObject->InheritsFrom("BDSBH4DBase"))
199 {
200 TH1* h = dynamic_cast<TH1*>(dirObject);
201 if (!h)
202 {continue;} // shouldn't happen but protect against bad dynamic cast access
203 int nDim;
204 bool BDSBH4Dtype = false;
205
206 if (dirObject->InheritsFrom("BDSBH4DBase"))
207 {
208 nDim = 4;
209 BDSBH4Dtype = true;
210 }
211 else
213
214 if (debug)
215 {gDirectory->pwd();}
216
217 std::string histPath = dirPath + "/";
218 histPath.erase(0,1); // erase leading '/'
219 std::string histName = std::string(h->GetName());
220 std::string histTitle = std::string(h->GetTitle());
221 TDirectory* outDir = output->GetDirectory(histPath.c_str());
222 if (!outDir)
223 {output->mkdir(histPath.c_str());} // this returns the parent dir for some stupid reason
224 // instead get the directory from the output, knowing it now exists
225 outDir = output->GetDirectory(histPath.c_str());
226 output->cd(histPath.c_str()); // change into it so new histograms are added to it
227
228 // create appropriate type of merge
229 HistogramAccumulator* acc = nullptr;
230 RBDS::MergeType mergeType = RBDS::DetermineMergeType(dir->GetName());
231 switch (mergeType)
232 {
233 case RBDS::MergeType::meanmerge:
234 {
235 acc = new HistogramAccumulatorMerge(h, nDim, histName, histTitle);
236 break;
237 }
238 case RBDS::MergeType::sum:
239 {
240 acc = new HistogramAccumulatorSum(h, nDim, histName, histTitle);
241 break;
242 }
243 case RBDS::MergeType::none:
244 default:
245 {continue; break;}
246 }
247
248 RBDS::HistogramPath path = {histPath, histName, acc, outDir, BDSBH4Dtype};
249 histograms.push_back(path);
250 std::cout << "Found histogram> " << histPath << histName << std::endl;
251 }
252 else
253 {continue;} // don't care about other objects
254 }
255 originalDir->cd();
256}
257
258RBDS::MergeType RBDS::DetermineMergeType(const std::string& parentDir)
259{
260 if (parentDir == "PerEntryHistograms")
261 {return RBDS::MergeType::meanmerge;}
262 else if (parentDir == "PerEntryHistogramSets")
263 {return RBDS::MergeType::meanmerge;}
264 else if (parentDir == "MergedHistograms")
265 {return RBDS::MergeType::meanmerge;}
266 else if (parentDir == "SimpleHistograms")
267 {return RBDS::MergeType::sum;}
268 else if (parentDir == "SimpleHistogramSets")
269 {return RBDS::MergeType::sum;}
270 else
271 {return RBDS::MergeType::none;}
272}
int dataVersion
Our data format version.
Header loader.
Definition: Header.hh:34
BDSOutputROOTEventHeader * header
Member that ROOT can map file data to locally.
Definition: Header.hh:44
void SetBranchAddress(TTree *t)
Set the branch addresses to address the contents of the file.
Definition: Header.cc:41
Class to combine histograms of mean with error on mean.
Class to Sum histogram.
Class to accumulate and merge histograms in different ways.
bool debug
Debug flag.
Definition: FileMapper.hh:113
HistogramMap()=delete
No need for default constructor.
std::vector< RBDS::HistogramPath > histograms
Storage of all objects.
Definition: FileMapper.hh:114
void MapDirectory(TDirectory *dir, TFile *output, const std::string &parentDir)
Definition: FileMapper.cc:164
bool IsBDSIMOutputFile(TFile *file, int *dataVersion=nullptr)
Definition: FileMapper.cc:66
bool IsREBDSIMOutputFile(TFile *file)
Definition: FileMapper.cc:93
bool GetFileType(TFile *file, std::string &fileType, int *dataVersion=nullptr)
Definition: FileMapper.cc:44
MergeType DetermineMergeType(const std::string &parentDir)
Determine merge type from parent directory name.
Definition: FileMapper.cc:258
bool IsREBDSIMOrCombineOutputFile(TFile *file)
Definition: FileMapper.cc:116
int DetermineDimensionality(TH1 *h)
Determine the number of dimensions of a histogram by dynamically casting.
Definition: FileMapper.cc:142
MergeType
Types of merging.
Definition: FileMapper.hh:82
void WarningMissingHistogram(const std::string &histName, const std::string &fileName)
Common print out method.
Definition: FileMapper.cc:147
Basic structure for accumulating histogram from rebdsim output files.
Definition: FileMapper.hh:73