BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
DataLoader.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "DataLoader.hh"
20#include "Beam.hh"
21#include "Event.hh"
22#include "FileMapper.hh"
23#include "ParticleData.hh"
24#include "Header.hh"
25#include "Model.hh"
26#include "Options.hh"
27#include "RBDSException.hh"
28#include "RebdsimTypes.hh"
29#include "Run.hh"
30
31#include "BDSDebug.hh"
32#include "BDSOutputROOTEventAperture.hh"
33#include "BDSOutputROOTEventCollimator.hh"
34#include "BDSOutputROOTEventSampler.hh"
35#include "BDSVersionData.hh"
36
37#include "TChain.h"
38#include "TFile.h"
39
40#include <algorithm>
41#include <cmath>
42#include <glob.h>
43#include <iostream>
44
45ClassImp(DataLoader)
46
47DataLoader::DataLoader(const std::string& fileName,
48 bool debugIn,
49 bool processSamplersIn,
50 bool allBranchesOnIn,
51 const RBDS::BranchMap* branchesToTurnOnIn,
52 bool backwardsCompatibleIn):
53 debug(debugIn),
54 processSamplers(processSamplersIn),
55 allBranchesOn(allBranchesOnIn),
56 branchesToTurnOn(branchesToTurnOnIn),
57 backwardsCompatible(backwardsCompatibleIn),
58 parChain(nullptr),
59 dataVersion(BDSIM_DATA_VERSION)
60{
61 CommonCtor(fileName);
62}
63
64DataLoader::~DataLoader()
65{
66 delete hea;
67 delete par;
68 delete bea;
69 delete opt;
70 delete mod;
71 delete evt;
72 delete run;
73
74 delete heaChain;
75 delete beaChain;
76 delete optChain;
77 delete modChain;
78 delete evtChain;
79 delete runChain;
80}
81
82void DataLoader::CommonCtor(const std::string& fileName)
83{
84 BuildInputFileList(fileName); // updates dataVersion
85
86 hea = new Header(debug);
87 par = new ParticleData(debug);
88 bea = new Beam(debug);
89 opt = new Options(debug);
90 mod = new Model(debug, dataVersion);
91 evt = new Event(debug, processSamplers, dataVersion);
92 run = new Run(debug, dataVersion);
93
94 heaChain = new TChain("Header", "Header");
95 if (dataVersion > 6)
96 {parChain = new TChain("ParticleData", "ParticleData");}
97 beaChain = new TChain("Beam", "Beam");
98 optChain = new TChain("Options", "Options");
99 modChain = new TChain("Model", "Model");
100 evtChain = new TChain("Event", "Event");
101 runChain = new TChain("Run", "Run");
102
105 ChainTrees();
106 SetBranchAddress(allBranchesOn, branchesToTurnOn);
107
108 if (dataVersion > 6)
109 {
110 parChain->GetEntry(0); // load particle data
111#ifdef __ROOTDOUBLE__
113#else
115 BDSOutputROOTEventCollimator::particleTable = par->particleData;
116 BDSOutputROOTEventAperture::particleTable = par->particleData;
117#endif
118 }
119}
120
121void DataLoader::BuildInputFileList(std::string inputPath)
122{
123 if (inputPath.empty())
124 {throw RBDSException("DataLoader::BuildInputFileList> no file specified");}
125
126 // wild card
127 std::vector<std::string> fileNamesTemp;
128 if (inputPath.find('*') != std::string::npos)
129 {
130 glob_t glob_result;
131 glob(inputPath.c_str(),GLOB_TILDE,nullptr,&glob_result);
132 for(unsigned int i=0;i<glob_result.gl_pathc;++i)
133 {fileNamesTemp.emplace_back(glob_result.gl_pathv[i]);}
134 globfree(&glob_result);
135 }
136 // single file
137 else if (inputPath.find(".root") != std::string::npos)
138 {fileNamesTemp.push_back(inputPath);}
139 // directory
140 else if (inputPath[inputPath.length()-1] == std::string("/"))
141 {
142 // find all files in directory
143 inputPath.append("/*.root");
144
145 glob_t glob_result;
146 glob(inputPath.c_str(),GLOB_TILDE,nullptr,&glob_result);
147 for (unsigned int i=0; i<glob_result.gl_pathc; ++i)
148 {fileNamesTemp.emplace_back(glob_result.gl_pathv[i]);}
149 globfree(&glob_result);
150 }
151
152 // loop over files and check they're the right type
153 int* fileDataVersion = nullptr; // for backwards compatibility don't try
154 if (!backwardsCompatible)
155 {
156 fileDataVersion = new int();
157 (*fileDataVersion) = 0;
158 }
159 for (const auto& fn : fileNamesTemp)
160 {
161 if (backwardsCompatible)
162 {fileNames.push_back(fn);} // don't check if header -> old files don't have this
163 else if (RBDS::IsBDSIMOutputFile(fn, fileDataVersion))
164 {
165 int value = fileDataVersion ? *fileDataVersion : -1;
166 std::cout << "Loading> \"" << fn << "\" : data version " << value << std::endl;
167 fileNames.push_back(fn);
168 dataVersion = fileDataVersion ? std::min(dataVersion, *fileDataVersion) : dataVersion;
169 }
170 else
171 {std::cout << fn << " is not a BDSIM output file - skipping!" << std::endl;}
172 }
173 delete fileDataVersion;
174
175 if (fileNames.empty())
176 {throw RBDSException("DataLoader - No valid files found - check input file path / name");}
177}
178
180{
181 // open file - this is the first opening so test here if it's valid
182 TFile* f = new TFile(fileNames[0].c_str());
183 if (f->IsZombie())
184 {throw RBDSException(__METHOD_NAME__,"No such file \"" + fileNames[0] + "\"");}
185
186 TList* kl = f->GetListOfKeys();
187 for (int i = 0; i < kl->GetEntries(); ++i)
188 {treeNames.emplace_back(std::string(kl->At(i)->GetName()));}
189
190 f->Close();
191 delete f;
192
193 if(debug)
194 {
195 for (const auto& tr : treeNames)
196 {std::cout << "DataLoader::BuildTreeNameList> " << tr << std::endl;}
197 }
198}
199
201{
202 TFile* f = new TFile(fileNames[0].c_str());
203 if (f->IsZombie())
204 {throw RBDSException(__METHOD_NAME__,"No such file \"" + fileNames[0] + "\"");}
205
206 TTree* mt = (TTree*)f->Get("Model");
207 if (!mt)
208 {
209 f->Close();
210 delete f;
211 return;
212 }
213
214 if (mt->GetEntries() == 0)
215 {
216 f->Close();
217 delete f;
218 return;
219 }
220
221 Model* modTemporary = new Model(false, dataVersion);
222 modTemporary->SetBranchAddress(mt);
223 mt->GetEntry(0);
224 allSamplerNames = modTemporary->SamplerNames();
225 allCSamplerNames = modTemporary->SamplerCNames();
226 allSSamplerNames = modTemporary->SamplerSNames();
227 if (processSamplers)
228 { // copy sampler names out
229 samplerNames = allSamplerNames;
230 samplerCNames = allCSamplerNames;
231 samplerSNames = allSSamplerNames;
232 }
233 // collimator names was only added in data version 4 - can leave as empty vector
234 if (dataVersion > 3)
235 {collimatorNames = modTemporary->CollimatorNames();}
236
237 f->Close();
238 delete f;
239 delete modTemporary;
240
241 if(debug)
242 {
243 for (const auto& n : branchNames)
244 {std::cout << "DataLoader::BuildEventBranchNameList> Non-sampler : " << n << std::endl;}
245 for (const auto& n : samplerNames)
246 {std::cout << "DataLoader::BuildEventBranchNameList> Sampler : " << n << std::endl;}
247 for (const auto& n : samplerCNames)
248 {std::cout << "DataLoader::BuildEventBranchNameList> SamplerC : " << n << std::endl;}
249 for (const auto& n : samplerSNames)
250 {std::cout << "DataLoader::BuildEventBranchNameList> SamplerS : " << n << std::endl;}
251 for (const auto& n : collimatorNames)
252 {std::cout << "DataLoader::BuildEventBranchNameList> Collimator : " << n << std::endl;}
253 }
254}
255
257{
258 // loop over files and chain trees
259 if (dataVersion > 6)
260 {parChain->Add(fileNames[0].c_str());} // only require 1 copy
261 for (const auto& filename : fileNames)
262 {
263 heaChain->Add(filename.c_str());
264 beaChain->Add(filename.c_str());
265 optChain->Add(filename.c_str());
266 modChain->Add(filename.c_str());
267 evtChain->Add(filename.c_str());
268 runChain->Add(filename.c_str());
269 }
270}
271
273 const RBDS::BranchMap* bToTurnOn)
274{
275 if (dataVersion > 6)
276 {par->SetBranchAddress(parChain);}
277 hea->SetBranchAddress(heaChain);
278 bea->SetBranchAddress(beaChain, true); // true = always turn on all branches
279 mod->SetBranchAddress(modChain, true); // true = always turn on all branches
280 opt->SetBranchAddress(optChain, true); // true = always turn on all branches
281 // note we can't parse the :: properly in the options tree so we turn on by default
282
283 const RBDS::VectorString* evtBranches = nullptr;
284 if (bToTurnOn)
285 {
286 if (bToTurnOn->find("Event.") != bToTurnOn->end())
287 {evtBranches = &(*bToTurnOn).at("Event.");}
288 if (evtBranches) // technically could be nullptr
289 {
290 for (const auto& bName: *evtBranches)
291 {
292 if (std::find(allSamplerNames.begin(), allSamplerNames.end(), bName + ".") != allSamplerNames.end())
293 {samplerNames.push_back(bName + "."); continue;}
294 if (std::find(allCSamplerNames.begin(), allCSamplerNames.end(), bName + ".") != allCSamplerNames.end())
295 {samplerCNames.push_back(bName + "."); continue;}
296 if (std::find(allSSamplerNames.begin(), allSSamplerNames.end(), bName + ".") != allSSamplerNames.end())
297 { samplerSNames.push_back(bName + "."); continue;}
298 }
299 }
300 }
301 evt->SetBranchAddress(evtChain, &samplerNames, allOn, evtBranches, &collimatorNames, &samplerCNames, &samplerSNames);
302
303 const RBDS::VectorString* runBranches = nullptr;
304 if (bToTurnOn)
305 {
306 if (bToTurnOn->find("Run.") != bToTurnOn->end())
307 {runBranches = &(*bToTurnOn).at("Run.");}
308 }
309 run->SetBranchAddress(runChain, allOn, runBranches);
310}
Information stored per sampler per event.
Beam loader.
Definition: Beam.hh:37
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Set the branch addresses to address the contents of the file.
Definition: Beam.cc:44
Loader for a ROOT file using classes used to generate the file.
Definition: DataLoader.hh:46
void SetBranchAddress(bool allOn=true, const RBDS::BranchMap *bToTurnOn=nullptr)
Map each chain to the member instance of each storage class in this class.
Definition: DataLoader.cc:272
void BuildEventBranchNameList()
Definition: DataLoader.cc:200
int dataVersion
Integer version of data loaded.
Definition: DataLoader.hh:136
void CommonCtor(const std::string &fileName)
Definition: DataLoader.cc:82
void BuildTreeNameList()
Open the first file in the file list and map the trees in it.
Definition: DataLoader.cc:179
void BuildInputFileList(std::string inputPath)
Build up the input file list.
Definition: DataLoader.cc:121
void ChainTrees()
Create a tree for each sampler and add all the files to it.
Definition: DataLoader.cc:256
Event loader.
Definition: Event.hh:50
void SetBranchAddress(TTree *t, const RBDS::VectorString *samplerNames=nullptr, bool allBranchesOn=false, const RBDS::VectorString *branchesToTurnOn=nullptr, const RBDS::VectorString *collimatorNamesIn=nullptr, const RBDS::VectorString *samplerCNamesIn=nullptr, const RBDS::VectorString *samplerSNamesIn=nullptr)
Definition: Event.cc:206
Header loader.
Definition: Header.hh:34
void SetBranchAddress(TTree *t)
Set the branch addresses to address the contents of the file.
Definition: Header.cc:41
Model loader.
Definition: Model.hh:36
std::vector< std::string > CollimatorNames() const
Access all the sampler branch names from the model.
Definition: Model.cc:91
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Set the branch addresses to address the contents of the file.
Definition: Model.cc:50
std::vector< std::string > SamplerNames() const
Access all the unique sampler names from the model.
Definition: Model.cc:73
Options loader.
Definition: Options.hh:36
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Set the branch addresses to address the contents of the file.
Definition: Options.cc:43
Particle Data loader.
Definition: ParticleData.hh:34
void SetBranchAddress(TTree *t)
Set the branch addresses to address the contents of the file.
Definition: ParticleData.cc:41
BDSOutputROOTParticleData * particleData
Member that ROOT can map file data to locally.
Definition: ParticleData.hh:44
General exception with possible name of object and message.
Class to overlay a run from a ROOT file with.
Definition: Run.hh:36
void SetBranchAddress(TTree *t, bool allBranchesOn=true, const RBDS::VectorString *branchesToTurnOn=nullptr)
Map the ROOT file to members in this class.
Definition: Run.cc:67
bool IsBDSIMOutputFile(TFile *file, int *dataVersion=nullptr)
Definition: FileMapper.cc:66