15#include <TCollection.h>
16#include <TDirectory.h>
22#include <TObjString.h>
43Bool_t CheckPackagesList(TList* list) {
44 for (
int i = 0; i < list->GetEntries() / 2; i++) {
45 if (list->At(i * 2)->InheritsFrom(
"Hal::Package") == kFALSE) {
return kFALSE; }
49Bool_t CheckAndMergeList(TList* prim, TList* sec) {
50 if (prim->GetEntries() != sec->GetEntries()) {
54 for (
int i = 0; i < prim->GetEntries() / 2; i++) {
55 TString name_a = ((TObjString*) prim->At(i * 2 + 1))->GetString();
56 TString name_b = ((TObjString*) sec->At(i * 2 + 1))->GetString();
57 Bool_t first_can_be_merged = prim->At(i * 2)->InheritsFrom(
"Hal::Package");
58 Bool_t second_can_be_merged = sec->At(i * 2)->InheritsFrom(
"Hal::Package");
59 if (name_a.EqualTo(name_b)) {
63 if (first_can_be_merged == kFALSE) {
64 Hal::Cout::PrintInfo(Form(
"First object cannot be merged (%s)", name_a.Data()), Hal::EInfo::kError);
66 if (second_can_be_merged == kFALSE) {
67 Hal::Cout::PrintInfo(Form(
"Second object cannot be merged (%s)", name_b.Data()), Hal::EInfo::kError);
69 if (!name_a.EqualTo(name_b) || !first_can_be_merged || !second_can_be_merged) {
74 for (
int i = 0; i < prim->GetEntries() / 2; i++) {
82TList* GetListObjects(TFile* file, TString dir_name, Bool_t must_be) {
83 TDirectory* dir = (TDirectory*) file->Get(dir_name);
85 if (must_be == kTRUE) {
86 Hal::Cout::PrintInfo(Form(
"%s directory not found in file", dir_name.Data()), Hal::EInfo::kCriticalError);
88 Hal::Cout::PrintInfo(Form(
"%s directory not found in file", dir_name.Data()), Hal::EInfo::kError);
92 TList* key_lists = dir->GetListOfKeys();
93 key_lists->SetOwner(kTRUE);
94 TList* objects =
new TList();
95 objects->SetOwner(kTRUE);
96 for (
int i = 0; i < key_lists->GetEntries(); i++) {
97 TKey* key = (TKey*) key_lists->At(i);
98 objects->AddAt(file->Get(Form(
"%s/%s", dir_name.Data(), key->GetName())), i * 2);
99 objects->AddAt(
new TObjString(key->GetName()), i * 2 + 1);
107Int_t mergeAnaFiles(TString filename, TFile* file1, TString outFile, TList* list_files) {
108 TList *prim_ana =
nullptr, *sec_ana =
nullptr;
109 TList *prim_meta =
nullptr, *sec_meta =
nullptr;
110 prim_ana = GetListObjects(file1,
"HalPhysics", kTRUE);
111 prim_meta = GetListObjects(file1,
"HalInfo", kFALSE);
113 if (!CheckPackagesList(prim_ana)) {
114 Hal::Cout::PrintInfo(
"HalPhysics contain class that cannot be merged by hal-merger", Hal::EInfo::kCriticalError);
118 if (!CheckPackagesList(prim_meta)) {
119 Hal::Cout::PrintInfo(
"HalInfo contain classes that cannot be merged by hal-merger", Hal::EInfo::kError);
124 if (prim_ana == NULL || prim_meta == NULL) {
125 if (prim_ana)
delete prim_ana;
126 if (prim_meta)
delete prim_meta;
133 for (
int i = 1; i < list_files->GetEntries(); i++) {
134 filename = ((TObjString*) list_files->At(i))->GetString();
135 TFile* file =
new TFile(filename);
136 if (file->IsZombie()) {
142 sec_ana = GetListObjects(file,
"HalPhysics", kTRUE);
143 sec_meta = GetListObjects(file,
"HalInfo", kFALSE);
144 if (sec_ana == NULL) {
155 if (sec_meta == NULL) {
166 if (CheckAndMergeList(prim_ana, sec_ana) == kFALSE) {
167 Hal::Cout::PrintInfo(
"Cannot merge HalPhysisc directory, incompatible objects", Hal::EInfo::kError);
171 if (sec_ana)
delete sec_ana;
172 if (sec_meta)
delete sec_meta;
175 if (CheckAndMergeList(prim_meta, sec_meta) == kFALSE) {
176 Hal::Cout::PrintInfo(
"Cannot merge HalInfo directory, incompatible objects", Hal::EInfo::kError);
190 if (sec_ana)
delete sec_ana;
191 if (sec_meta)
delete sec_meta;
197 TFile* file =
new TFile(outFile,
"recreate");
199 TDirectory* d = gDirectory;
202 for (
int i = 0; i < prim_meta->GetEntries() / 2; i++) {
203 prim_meta->At(i * 2)->Write(((TObjString*) prim_meta->At(i * 2 + 1))->GetString());
205 d->mkdir(
"HalPhysics");
207 for (
int i = 0; i < prim_ana->GetEntries() / 2; i++) {
208 prim_ana->At(i * 2)->Write(((TObjString*) prim_ana->At(i * 2 + 1))->GetString());
213Int_t mergeQAFiles(TString filename, TFile* file1, TString outFile, TList* list_files) {
214 TList* histos = GetListObjects(file1,
"HalQA", kTRUE);
217 for (
int i = 1; i < list_files->GetEntries(); i++) {
218 filename = ((TObjString*) list_files->At(i))->GetString();
219 TFile* file =
new TFile(filename);
220 if (file->IsZombie()) {
226 TList* histos2 = GetListObjects(file,
"HalQA", kTRUE);
227 CheckAndMergeList(histos, histos2);
230 TFile* file =
new TFile(outFile,
"recreate");
232 file->mkdir(
"HalQA");
234 for (
int i = 0; i < histos->GetEntries() / 2; i++) {
235 histos->At(i * 2)->Write(((TObjString*) histos->At(i * 2 + 1))->GetString());
242Int_t mergeFiles(TString outFile, TList* list_files) {
243 TString filename = ((TObjString*) list_files->At(0))->GetString();
244 TFile* file1 =
new TFile(filename);
245 TObject* qa = file1->Get(
"HalQA");
247 return mergeQAFiles(filename, file1, outFile, list_files);
249 return mergeAnaFiles(filename, file1, outFile, list_files);
267int main(
int argc,
char* argv[]) {
271 Hal::Cout::Text(
"1) name of xml file (with .xml extension) with list of files to merge",
"M");
272 Hal::Cout::Text(
"2) name of output root file and input root files (like for hadd: "
273 "out.root input1.root input2.root ...)",
275 Hal::Cout::Text(
"3) --n=X + one of options above to specify maximum number of files "
280 TString opt = argv[1];
281 if (opt ==
"--help") {
283 Hal::Cout::Text(
"1) name of xml file (with .xml extension) with list of files to "
286 Hal::Cout::Text(
"2) name of output root file and input root files (like for hadd: "
287 "out.root input1.root input2.root ...)",
289 Hal::Cout::Text(
"3) --n=X + one of options above to specify maximum number of files "
294 gSystem->Load(
"libTree");
295 gErrorIgnoreLevel = kError;
298 TList* list_files =
new TList();
300 TString argname = argv[1];
303 if (argname.BeginsWith(
"--n=")) {
304 TString val(argname(4, argname.Length() - 4));
309 if (argname.EndsWith(
".xml")) {
310 Hal::Cout::Text(Form(
"Opening XML file %s", argname.Data()),
"L", kWhite);
317 }
else if (argname.EndsWith(
".root") || argname.EndsWith(
".root_t")) {
319 outputFile = argname;
320 for (
int i = arg_pos; i < argc; i++) {
321 list_files->AddLast(
new TObjString(argv[i]));
327 if (split < 2 || split >= list_files->GetEntries()) {
328 mergeFiles(outputFile, list_files);
331 Int_t entries = list_files->GetEntries();
332 Int_t nSteps = entries / split;
333 if (entries % split != 0) nSteps++;
334 TString file[2] = {
"temp_1.root_t",
"temp_2.root_t"};
335 for (
int iStep = 0; iStep < nSteps; iStep++) {
336 Int_t record = iStep * split;
340 while (record + j < entries && j < split) {
341 name = name + space + ((TObjString*) list_files->At(record + j))->GetString();
344 TString outFile = file[iStep % 2];
345 if (iStep > 0) { name = Form(
"%s %s", name.Data(), (file[(iStep + 1) % 2]).Data()); }
346 if (iStep + 1 == nSteps) { outFile = argname; }
347 gSystem->Exec(Form(
"hal-merger %s %s", outFile.Data(), name.Data()));
348 if (iStep + 1 == nSteps) {
349 if (Hal::Std::FileExists(file[0])) gSystem->Exec(
"rm temp_1.root_t ");
350 if (Hal::Std::FileExists(file[1])) gSystem->Exec(
"rm temp_2.root_t ");
static void Text(TString text, TString option="L", Color_t color=-1)
static void PrintInfo(TString text, Hal::EInfo status)
static void Stars(Color_t color=-1)
static void FailSucced(TString value, TString flag, Color_t color)
void Add(const Package *pack)
Int_t GetNChildren() const
XMLNode * GetChild(TString name, Int_t count=0) const
XMLAttrib * GetAttrib(TString name) const