22#include "FileMapper.hh"
25#include "BDSOutputROOTEventHeader.hh"
37int main(
int argc,
char* argv[])
41 std::cout <<
"usage: bdsimCombine result.root file1.root file2.root ..." << std::endl;
46 std::vector<std::string> inputFiles;
47 for (
int i = 2; i < argc; ++i)
48 {inputFiles.emplace_back(std::string(argv[i]));}
50 if (inputFiles[0].find(
'*') != std::string::npos)
52 std::vector<std::string> fileNamesTemp;
54 glob(inputFiles[0].c_str(),GLOB_TILDE,
nullptr,&glob_result);
55 for (
unsigned int i=0; i<glob_result.gl_pathc; ++i)
56 {fileNamesTemp.emplace_back(glob_result.gl_pathv[i]);}
57 globfree(&glob_result);
58 inputFiles = fileNamesTemp;
62 if (inputFiles.size() == 1)
64 std::cout <<
"Only one input file provided \"" << inputFiles[0] <<
"\" - no point." << std::endl;
68 std::string outputFile = std::string(argv[1]);
69 if (outputFile.find(
'*') != std::string::npos)
71 std::cerr <<
"First argument for output file \"" << outputFile <<
"\" contains an *." << std::endl;
72 std::cerr <<
"Should only be a singular file - check order of arguments." << std::endl;
77 TChain* eventsMerged =
new TChain(
"Event");
78 for (
const auto& filename : inputFiles)
79 {eventsMerged->Add(filename.c_str());}
80 std::cout <<
"Beginning merge of Event Tree" << std::endl;
81 Long64_t operationCode = eventsMerged->Merge(outputFile.c_str());
82 if (operationCode == 0)
84 std::cerr <<
"Problem in TTree::Merge opening output file \"" << outputFile <<
"\"" << std::endl;
88 {std::cout <<
"Finished merge of Event Tree" << std::endl;}
92 unsigned long long int nOriginalEvents = 0;
93 unsigned long long int nEventsRequested = 0;
94 unsigned long long int nEventsInFile = 0;
95 unsigned long long int nEventsInFileSkipped = 0;
96 unsigned int distrFileLoopNTimes = 0;
97 bool skimmedFile =
false;
98 unsigned long int i = 0;
99 std::cout <<
"Counting number of original events from headers of files" << std::endl;
100 std::vector<unsigned long long int> nEventsPerTree;
101 for (
const auto& filename : inputFiles)
103 TFile* f =
new TFile(filename.c_str(),
"READ");
106 std::cout <<
"File \"" << filename <<
"\" skipped as not a valid BDSIM file" << std::endl;
112 std::cout <<
"Accumulating> " << filename << std::endl;
113 TTree* headerTree =
dynamic_cast<TTree*
>(f->Get(
"Header"));
116 std::cerr <<
"Problem getting header from file " << filename << std::endl;
124 Long64_t nEntriesHeader = headerTree->GetEntries();
125 headerTree->GetEntry(nEntriesHeader - 1);
137 unsigned long long int nEventsThisFile = 0;
138 TTree* eventTree =
dynamic_cast<TTree*
>(f->Get(
"Event"));
140 {nEventsThisFile = (
unsigned long long int)eventTree->GetEntries();}
141 nEventsPerTree.push_back(nEventsThisFile);
151 {std::cerr <<
"No valid files found" << std::endl;
return 1;}
155 TFile* input =
nullptr;
156 bool validFile =
false;
160 if (i > (
unsigned long int)inputFiles.size())
162 input =
new TFile(inputFiles[i].c_str(),
"READ");
167 TFile* output =
new TFile(outputFile.c_str(),
"UPDATE");
168 if (output->IsZombie())
169 {std::cerr <<
"Could not reopen output file to add other trees";
return 1;}
172 headerOut->
Fill(std::vector<std::string>(), inputFiles);
180 TTree* headerTree =
new TTree(
"Header",
"BDSIM Header");
181 headerTree->Branch(
"Header.",
"BDSOutputROOTEventHeader", headerOut);
185 std::cout <<
"Merging rest of file contents" << std::endl;
186 std::vector<std::string> treeNames = {
"ParticleData",
"Beam",
"Options",
"Model",
"Run"};
187 for (
const auto& tn : treeNames)
189 TTree* original =
dynamic_cast<TTree*
>(input->Get(tn.c_str()));
192 std::cerr <<
"Failed to load Tree named " << tn << std::endl;
197 original->CloneTree();
200 TTree* eventCombineInfoTree =
new TTree(
"EventCombineInfo",
"EventCombineInfo");
201 UInt_t originalID = 0;
202 eventCombineInfoTree->Branch(
"combinedFileIndex", &originalID);
203 for (
int fileIndex = 0; fileIndex < (int)nEventsPerTree.size(); fileIndex++)
205 unsigned long long int v = nEventsPerTree[fileIndex];
206 for (
unsigned long long int j = 0; j < v; j++)
208 originalID = (UInt_t)fileIndex;
209 eventCombineInfoTree->Fill();
213 TTree* eventTree =
dynamic_cast<TTree*
>(output->Get(
"Event"));
215 {eventTree->AddFriend(eventCombineInfoTree);}
218 output->Write(
nullptr, TObject::kOverwrite);
223 std::cout <<
"Combined result of " << inputFiles.size() <<
" files written to: " << outputFile << std::endl;
224 std::cout <<
"Run histograms are not summed" << std::endl;
bool IsBDSIMOutputFile(TFile *file, int *dataVersion=nullptr)