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