Heavy ion Analysis Libriares
Loading...
Searching...
No Matches
hal_merger.cpp
1/*
2 * mpd_merger.cpp
3 *
4 * Created on: 30-04-2022
5 * Author: Daniel Wielanek
6 * E-mail: daniel.wielanek@gmail.com
7 * Warsaw University of Technology, Faculty of Physics
8 */
9
10#include "Cout.h"
11#include "Package.h"
12#include "Std.h"
13#include "XMLNode.h"
14
15#include <TCollection.h>
16#include <TDirectory.h>
17#include <TError.h>
18#include <TFile.h>
19#include <TKey.h>
20#include <TList.h>
21#include <TNamed.h>
22#include <TObjString.h>
23#include <TObject.h>
24#include <TString.h>
25#include <TSystem.h>
26
27
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; }
46 }
47 return kTRUE;
48}
49Bool_t CheckAndMergeList(TList* prim, TList* sec) {
50 if (prim->GetEntries() != sec->GetEntries()) {
51 Hal::Cout::PrintInfo("Prim !=Sec", Hal::EInfo::kError);
52 return kFALSE;
53 }
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)) {
60 } else {
61 Hal::Cout::PrintInfo("Names not equal", Hal::EInfo::kError);
62 }
63 if (first_can_be_merged == kFALSE) {
64 Hal::Cout::PrintInfo(Form("First object cannot be merged (%s)", name_a.Data()), Hal::EInfo::kError);
65 }
66 if (second_can_be_merged == kFALSE) {
67 Hal::Cout::PrintInfo(Form("Second object cannot be merged (%s)", name_b.Data()), Hal::EInfo::kError);
68 }
69 if (!name_a.EqualTo(name_b) || !first_can_be_merged || !second_can_be_merged) {
70 delete sec;
71 return kFALSE;
72 }
73 }
74 for (int i = 0; i < prim->GetEntries() / 2; i++) {
75 Hal::Package* A = (Hal::Package*) prim->At(i * 2);
76 Hal::Package* B = (Hal::Package*) sec->At(i * 2);
77 A->Add(B);
78 }
79 return kTRUE;
80}
81
82TList* GetListObjects(TFile* file, TString dir_name, Bool_t must_be) {
83 TDirectory* dir = (TDirectory*) file->Get(dir_name);
84 if (dir == NULL) {
85 if (must_be == kTRUE) {
86 Hal::Cout::PrintInfo(Form("%s directory not found in file", dir_name.Data()), Hal::EInfo::kCriticalError);
87 } else {
88 Hal::Cout::PrintInfo(Form("%s directory not found in file", dir_name.Data()), Hal::EInfo::kError);
89 }
90 return NULL;
91 } else {
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);
100 }
101 dir->DeleteAll();
102 delete dir;
103 return objects;
104 }
105}
106
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);
112 if (prim_ana)
113 if (!CheckPackagesList(prim_ana)) {
114 Hal::Cout::PrintInfo("HalPhysics contain class that cannot be merged by hal-merger", Hal::EInfo::kCriticalError);
115 return 0;
116 }
117 if (prim_meta)
118 if (!CheckPackagesList(prim_meta)) {
119 Hal::Cout::PrintInfo("HalInfo contain classes that cannot be merged by hal-merger", Hal::EInfo::kError);
120 return 0;
121 }
122 file1->Close();
123 delete file1;
124 if (prim_ana == NULL || prim_meta == NULL) {
125 if (prim_ana) delete prim_ana;
126 if (prim_meta) delete prim_meta;
127 Hal::Cout::FailSucced(Form("Opening primary file: %s ", filename.Data()), " FAIL ", kRed);
128 return 0;
129 } else {
130 Hal::Cout::FailSucced(Form("Opening primary file: %s ", filename.Data()), " OK ", kGreen);
131 }
132
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()) {
137 Hal::Cout::FailSucced(Form("Zombie file %s", filename.Data()), "FATAL", kRed);
138 file->Close();
139 delete file;
140 continue;
141 }
142 sec_ana = GetListObjects(file, "HalPhysics", kTRUE);
143 sec_meta = GetListObjects(file, "HalInfo", kFALSE);
144 if (sec_ana == NULL) {
145 Hal::Cout::PrintInfo(Form("No HalPhysics in %s", filename.Data()), Hal::EInfo::kError);
146 Hal::Cout::FailSucced(Form("Error opening file %s", filename.Data()), "FATAL", kRed);
147 file->Close();
148 delete file;
149 if (sec_meta) {
150 delete sec_meta;
151 sec_meta = NULL;
152 }
153 continue;
154 }
155 if (sec_meta == NULL) {
156 Hal::Cout::PrintInfo(Form("No HalInfo in %s", filename.Data()), Hal::EInfo::kError);
157 Hal::Cout::FailSucced(Form("Error opening file %s", filename.Data()), "FATAL", kRed);
158 file->Close();
159 delete file;
160 if (sec_ana) {
161 delete sec_ana;
162 sec_ana = NULL;
163 }
164 continue;
165 }
166 if (CheckAndMergeList(prim_ana, sec_ana) == kFALSE) {
167 Hal::Cout::PrintInfo("Cannot merge HalPhysisc directory, incompatible objects", Hal::EInfo::kError);
168 Hal::Cout::FailSucced(Form("Error opening file %s", filename.Data()), "FATAL", kRed);
169 file->Close();
170 delete file;
171 if (sec_ana) delete sec_ana;
172 if (sec_meta) delete sec_meta;
173 continue;
174 }
175 if (CheckAndMergeList(prim_meta, sec_meta) == kFALSE) {
176 Hal::Cout::PrintInfo("Cannot merge HalInfo directory, incompatible objects", Hal::EInfo::kError);
177 Hal::Cout::FailSucced(Form("Error opening file %s", filename.Data()), "FATAL", kRed);
178 file->Close();
179 delete file;
180 if (sec_ana) {
181 delete sec_ana;
182 sec_ana = NULL;
183 }
184 if (sec_meta) {
185 delete sec_meta;
186 sec_meta = NULL;
187 }
188 continue;
189 }
190 if (sec_ana) delete sec_ana;
191 if (sec_meta) delete sec_meta;
192 Hal::Cout::FailSucced(Form("Closing added file: %s ", filename.Data()), " OK ", kGreen);
193 file->Close();
194 delete file;
195 }
196 Hal::Cout::Text(Form("Saving file: %s", outFile.Data()), "L", kWhite);
197 TFile* file = new TFile(outFile, "recreate");
198 file->cd();
199 TDirectory* d = gDirectory;
200 d->mkdir("HalInfo");
201 d->cd("HalInfo");
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());
204 }
205 d->mkdir("HalPhysics");
206 d->cd("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());
209 }
210 file->Close();
211 return 0;
212}
213Int_t mergeQAFiles(TString filename, TFile* file1, TString outFile, TList* list_files) {
214 TList* histos = GetListObjects(file1, "HalQA", kTRUE);
215 file1->Close();
216 delete file1;
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()) {
221 Hal::Cout::FailSucced(Form("Zombie file %s", filename.Data()), "FATAL", kRed);
222 file->Close();
223 delete file;
224 continue;
225 }
226 TList* histos2 = GetListObjects(file, "HalQA", kTRUE);
227 CheckAndMergeList(histos, histos2);
228 delete histos2;
229 }
230 TFile* file = new TFile(outFile, "recreate");
231 file->cd();
232 file->mkdir("HalQA");
233 file->cd("HalQA");
234 for (int i = 0; i < histos->GetEntries() / 2; i++) {
235 histos->At(i * 2)->Write(((TObjString*) histos->At(i * 2 + 1))->GetString());
236 }
237 file->Close();
238 delete file;
239 return 1;
240}
241
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");
246 if (qa != nullptr) {
247 return mergeQAFiles(filename, file1, outFile, list_files);
248 } else {
249 return mergeAnaFiles(filename, file1, outFile, list_files);
250 }
251}
252
267int main(int argc, char* argv[]) {
268 if (argc < 2) {
269 Hal::Cout::PrintInfo("No arguments", Hal::EInfo::kError);
270 Hal::Cout::Text("You can use following arguments : ", "M");
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 ...)",
274 "M");
275 Hal::Cout::Text("3) --n=X + one of options above to specify maximum number of files "
276 "merged at once",
277 "M");
278 return 0;
279 } else {
280 TString opt = argv[1];
281 if (opt == "--help") {
282 Hal::Cout::Text("You can use following arguments : ", "M");
283 Hal::Cout::Text("1) name of xml file (with .xml extension) with list of files to "
284 "merge",
285 "M");
286 Hal::Cout::Text("2) name of output root file and input root files (like for hadd: "
287 "out.root input1.root input2.root ...)",
288 "M");
289 Hal::Cout::Text("3) --n=X + one of options above to specify maximum number of files "
290 "merged at once",
291 "M");
292 }
293 }
294 gSystem->Load("libTree");
295 gErrorIgnoreLevel = kError;
296 Hal::Cout::Stars(kWhite);
297
298 TList* list_files = new TList();
299 TString outputFile;
300 TString argname = argv[1];
301 Int_t split = 0;
302 Int_t arg_pos = 2;
303 if (argname.BeginsWith("--n=")) {
304 TString val(argname(4, argname.Length() - 4));
305 argname = argv[2];
306 split = val.Atoi();
307 arg_pos = 3;
308 }
309 if (argname.EndsWith(".xml")) {
310 Hal::Cout::Text(Form("Opening XML file %s", argname.Data()), "L", kWhite);
311 Hal::XMLFile parser(argname);
312 Hal::XMLNode* root = parser.GetRootNode();
313 outputFile = root->GetAttrib("outfile")->GetValue();
314 for (int i = 0; i < root->GetNChildren(); i++) {
315 list_files->AddLast(new TObjString(root->GetChild(i)->GetValue()));
316 }
317 } else if (argname.EndsWith(".root") || argname.EndsWith(".root_t")) {
318 Hal::Cout::Text("Using direct list of root files", "L", kWhite);
319 outputFile = argname;
320 for (int i = arg_pos; i < argc; i++) {
321 list_files->AddLast(new TObjString(argv[i]));
322 }
323 } else {
324 Hal::Cout::Text("wrong file extension !", "M", kRed);
325 return 0;
326 }
327 if (split < 2 || split >= list_files->GetEntries()) {
328 mergeFiles(outputFile, list_files);
329 } else {
330 --split;
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;
337 Int_t j = 0;
338 TString name = "";
339 TString space = " ";
340 while (record + j < entries && j < split) {
341 name = name + space + ((TObjString*) list_files->At(record + j))->GetString();
342 j++;
343 }
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) { // clean up temp files if present
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 ");
351 }
352 }
353 }
354 delete list_files;
355
356 return 0;
357}
static void Text(TString text, TString option="L", Color_t color=-1)
Definition Cout.cxx:92
static void PrintInfo(TString text, Hal::EInfo status)
Definition Cout.cxx:370
static void Stars(Color_t color=-1)
Definition Cout.cxx:150
static void FailSucced(TString value, TString flag, Color_t color)
Definition Cout.cxx:382
void Add(const Package *pack)
Definition Package.cxx:254
TString GetValue() const
Definition XMLNode.h:45
Int_t GetNChildren() const
Definition XMLNode.h:104
XMLNode * GetChild(TString name, Int_t count=0) const
Definition XMLNode.cxx:93
XMLAttrib * GetAttrib(TString name) const
Definition XMLNode.cxx:104
TString GetValue() const
Definition XMLNode.h:120