21#include "FileMapper.hh"
24#include "BDSOutputROOTEventHeader.hh"
36int main(
int argc,
char* argv[])
40 std::cout <<
"usage: bdsimCombine result.root file1.root file2.root ..." << std::endl;
45 std::vector<std::string> inputFiles;
46 for (
int i = 2; i < argc; ++i)
47 {inputFiles.emplace_back(std::string(argv[i]));}
49 if (inputFiles[0].find(
'*') != std::string::npos)
51 std::vector<std::string> fileNamesTemp;
53 glob(inputFiles[0].c_str(),GLOB_TILDE,
nullptr,&glob_result);
54 for (
unsigned int i=0; i<glob_result.gl_pathc; ++i)
55 {fileNamesTemp.emplace_back(glob_result.gl_pathv[i]);}
56 globfree(&glob_result);
57 inputFiles = fileNamesTemp;
61 if (inputFiles.size() == 1)
63 std::cout <<
"Only one input file provided \"" << inputFiles[0] <<
"\" - no point." << std::endl;
67 std::string outputFile = std::string(argv[1]);
68 if (outputFile.find(
'*') != std::string::npos)
70 std::cerr <<
"First argument for output file \"" << outputFile <<
"\" contains an *." << std::endl;
71 std::cerr <<
"Should only be a singular file - check order of arguments." << std::endl;
76 TChain* eventsMerged =
new TChain(
"Event");
77 for (
const auto& filename : inputFiles)
78 {eventsMerged->Add(filename.c_str());}
79 std::cout <<
"Beginning merge of Event Tree" << std::endl;
80 Long64_t operationCode = eventsMerged->Merge(outputFile.c_str());
81 if (operationCode == 0)
83 std::cerr <<
"Problem in TTree::Merge opening output file \"" << outputFile <<
"\"" << std::endl;
87 {std::cout <<
"Finished merge of Event Tree" << std::endl;}
91 unsigned long long int nOriginalEvents = 0;
92 unsigned long long int nEventsRequested = 0;
93 unsigned long long int nEventsInFile = 0;
94 unsigned long long int nEventsInFileSkipped = 0;
95 unsigned int distrFileLoopNTimes = 0;
96 bool skimmedFile =
false;
97 unsigned long int i = 0;
98 std::cout <<
"Counting number of original events from headers of files" << std::endl;
99 std::vector<unsigned long long int> nEventsPerTree;
100 for (
const auto& filename : inputFiles)
102 TFile* f =
new TFile(filename.c_str(),
"READ");
105 std::cout <<
"File \"" << filename <<
"\" skipped as not a valid BDSIM file" << std::endl;
111 std::cout <<
"Accumulating> " << filename << std::endl;
112 TTree* headerTree =
dynamic_cast<TTree*
>(f->Get(
"Header"));
115 std::cerr <<
"Problem getting header from file " << filename << std::endl;
123 Long64_t nEntriesHeader = headerTree->GetEntries();
124 headerTree->GetEntry(nEntriesHeader - 1);
136 unsigned long long int nEventsThisFile = 0;
137 TTree* eventTree =
dynamic_cast<TTree*
>(f->Get(
"Event"));
139 {nEventsThisFile = (
unsigned long long int)eventTree->GetEntries();}
140 nEventsPerTree.push_back(nEventsThisFile);
150 {std::cerr <<
"No valid files found" << std::endl;
return 1;}
154 TFile* input =
nullptr;
155 bool validFile =
false;
159 if (i > (
unsigned long int)inputFiles.size())
161 input =
new TFile(inputFiles[i].c_str(),
"READ");
166 TFile* output =
new TFile(outputFile.c_str(),
"UPDATE");
167 if (output->IsZombie())
168 {std::cerr <<
"Could not reopen output file to add other trees";
return 1;}
171 headerOut->
Fill(std::vector<std::string>(), inputFiles);
179 TTree* headerTree =
new TTree(
"Header",
"BDSIM Header");
180 headerTree->Branch(
"Header.",
"BDSOutputROOTEventHeader", headerOut);
184 std::cout <<
"Merging rest of file contents" << std::endl;
185 std::vector<std::string> treeNames = {
"ParticleData",
"Beam",
"Options",
"Model",
"Run"};
186 for (
const auto& tn : treeNames)
188 TTree* original =
dynamic_cast<TTree*
>(input->Get(tn.c_str()));
191 std::cerr <<
"Failed to load Tree named " << tn << std::endl;
196 original->CloneTree();
199 TTree* eventCombineInfoTree =
new TTree(
"EventCombineInfo",
"EventCombineInfo");
200 UInt_t originalID = 0;
201 eventCombineInfoTree->Branch(
"combinedFileIndex", &originalID);
202 for (
int fileIndex = 0; fileIndex < (int)nEventsPerTree.size(); fileIndex++)
204 unsigned long long int v = nEventsPerTree[fileIndex];
205 for (
unsigned long long int j = 0; j < v; j++)
207 originalID = (UInt_t)fileIndex;
208 eventCombineInfoTree->Fill();
212 TTree* eventTree =
dynamic_cast<TTree*
>(output->Get(
"Event"));
214 {eventTree->AddFriend(eventCombineInfoTree);}
217 output->Write(
nullptr, TObject::kOverwrite);
222 std::cout <<
"Combined result of " << inputFiles.size() <<
" files written to: " << outputFile << std::endl;
223 std::cout <<
"Run histograms are not summed" << std::endl;
bool IsBDSIMOutputFile(TFile *file, int *dataVersion=nullptr)