ATLAS Offline Software
Loading...
Searching...
No Matches
LArQuickHistMerge.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//Standalone compilation:
6//g++ -g -o mergetest.exe `root-config --libs --cflags` -L InstallArea/i686-slc5-gcc43-opt/lib/ -l DataQualityUtils LArHistMerge.version2.cxx
7
8#include "TSystem.h"
9#include "TH1.h"
10#include "TH2.h"
11#include "TFile.h"
12#include "TKey.h"
13#include "TTree.h"
14
15#include <iostream>
16#include <string>
17#include <string_view>
18#include <vector>
19#include <fstream>
20
23
24const int MAXSKIPPEDFILES = 10;
25const float MAXSKIPPEDFILESFRACTION = 0.1;
26
27
28TFile* openWithRetry(const char* path, const unsigned nTrys=3) {
29 TFile* f=nullptr;
30 unsigned iTry=0;
31 unsigned sleepSeconds=30;
32 while (!f && iTry<nTrys) {
33 f=TFile::Open(path,"READ");
34 if (!f || !(f->IsOpen())) {
35 ++iTry;
36 std::cout << "WARNING: Failed to open file " << path << " on " << iTry << ". attempt." << std::endl;
37 if (iTry<nTrys) {
38 std::cout << "Will re-try after " << sleepSeconds << " seconds..." << std::endl;
39 sleep(sleepSeconds);
40 f=nullptr;
41 sleepSeconds*=2;
42 }
43 else {//no more attempts
44 std::cout << "No more retrys" << std::endl;
45 }
46 }//end if file not open
47 }// end while
48 return f;
49}
50
52
53public:
54
55 explicit histCollection(bool debug=false) : m_dbg(debug) {};
56 void addDirectory(TDirectory* dir, const std::string& dirName);
57 size_t size() {return m_data.size();};
58 void addFile(TFile* in);
59 void print();
60 void write(TFile* out);
61
62 void addExclusion(const std::string& dir);
63
64private:
66 public:
67 histPerDir_t(const std::string& nameIn, TObject* objIn, TTree* md, bool dbg=false);
68 std::string name;
69 TObject* obj;
70 void (*mergeMethod)(TObject* a, const TObject* b);
71 };
72
73 struct histDir_t {
74 explicit histDir_t(TTree* mdIn): md(mdIn) {};
75 std::vector<histPerDir_t> histos;
76 TTree* md;
77 };
78
79
80private:
81 bool isExcluded(const std::string& dir);
82 std::map<std::string,histDir_t, std::less<>> m_data;
83 bool m_dbg;
84 std::vector<std::string> m_exclusion;
85
86};
87
88
89void histCollection::addExclusion(const std::string& dir) {
90 m_exclusion.push_back(dir);
91 return;
92}
93
94bool histCollection::isExcluded(const std::string& dir) {
95
96 const size_t firstSlash=dir.find('/',1);
97 if (firstSlash==std::string::npos) return false;
98
99 std::vector<std::string>::const_iterator it=m_exclusion.begin();
100 std::vector<std::string>::const_iterator it_e=m_exclusion.end();
101 for(;it!=it_e;++it) {
102 const std::string& excl=*it;
103 const size_t s=excl.size();
104 //std::cout << "Comparing " << dir << " (index "<< firstSlash <<") with " << excl << std::endl;
105 if (dir.compare(firstSlash,s,excl)==0) {
106 return true;
107 }
108 }
109 return false;
110}
111
112
114 auto it=m_data.begin();
115 auto it_e=m_data.end();
116 for(;it!=it_e;++it) {
117 const histDir_t& hd=it->second;
118 std::cout << "Dir: " << it->first <<" has "<<hd.histos.size()<<" histos"<<std::endl;
119 std::vector<histPerDir_t>::const_iterator it1=hd.histos.begin();
120 std::vector<histPerDir_t>::const_iterator it1_e=hd.histos.end();
121 for (;it1!=it1_e;++it1)
122 std::cout << "\t" << it1->name << std::endl;
123 }
124
125 std::cout << "\nExclusion List: " << std::endl;
126 std::vector<std::string>::const_iterator sit=m_exclusion.begin();
127 std::vector<std::string>::const_iterator sit_e=m_exclusion.end();
128 for(;sit!=sit_e;++sit)
129 std::cout << "\t" << *sit << std::endl;
130
131 return;
132}
133
134template<class HIST>
135void defaultMerge(TObject* a, const TObject* b) {
136 static_cast<HIST*>(a)->Add(static_cast<const HIST*>(b));
137 return;
138}
139
140void weightedAverageTH1 ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
141 TH1* a1=(dynamic_cast<TH1*>(a));
142 const TH1* b1=dynamic_cast<const TH1*>(b);
143 if (!b1 || !a1)
144 std::cout << "ERROR in weightedAverageTH1: Object not of type TH1" << std::endl;
145 else
147 return;
148}
149
150void weightedAverageTH2 ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
151 TH2* a1=(dynamic_cast<TH2*>(a));
152 const TH2* b1=(dynamic_cast<const TH2*>(b));
153 if (!b1 || !a1)
154 std::cout << "ERROR in weightedAverageTH2: Object not of type TH2" << std::endl;
155 else
157 return;
158}
159
160void weightedEff ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
161 TH1* a1=(dynamic_cast<TH1*>(a));
162 const TH1* b1=(dynamic_cast<const TH1*>(b));
163 if (!b1 || !a1)
164 std::cout << "ERROR in weightedEff: Object not of type TH1" << std::endl;
165 else
167 return;
168}
169
170void mergeRMS ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
171 TH1* a1=(dynamic_cast<TH1*>(a));
172 const TH1* b1=dynamic_cast<const TH1*>(b);
173 if (!b1 || !a1)
174 std::cout << "ERROR in mergeRMS: Object not of type TH1" << std::endl;
175 else
177 return;
178}
179
180void RMSpercentDeviation ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
181 TH1* a1=(dynamic_cast<TH1*>(a));
182 const TH1* b1=dynamic_cast<const TH1*>(b);
183 if (!b1 || !a1)
184 std::cout << "ERROR in RMSpercentDeviation: Object not of type TH1" << std::endl;
185 else
187 return;
188}
189
190void perBinEffPerCent ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
191 TH1* a1=(dynamic_cast<TH1*>(a));
192 const TH1* b1=dynamic_cast<const TH1*>(b);
193 if (!b1 || !a1)
194 std::cout << "ERROR in getBinEffPerCent: Object not of type TH1" << std::endl;
195 else
197 return;
198}
199
200void lowerLB ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
201 TH1* a1=(dynamic_cast<TH1*>(a));
202 const TH1* b1=dynamic_cast<const TH1*>(b);
203 if (!b1 || !a1)
204 std::cout << "ERROR in lowerLB: Object not of type TH1" << std::endl;
205 else
207 return;
208}
209
210void identical ATLAS_NOT_THREAD_SAFE (TObject* a, const TObject* b) {
211 TH1* a1=(dynamic_cast<TH1*>(a));
212 const TH1* b1=dynamic_cast<const TH1*>(b);
213 TH2* c1=(dynamic_cast<TH2*>(a));
214 const TH2* d1=dynamic_cast<const TH2*>(b);
215 if (a1 and b1){
217 } else if (c1 and d1){
219 } else {
220 std::cout << "ERROR in identical: Object not of type THist" << std::endl;
221 std::cout << a1 << " " << b1 << " " << c1 << " " <<d1 <<std::endl;
222 }
223 return;
224}
225
226
227histCollection::histPerDir_t::histPerDir_t(const std::string& nameIn, TObject* objIn, TTree* md, bool dbg) :
228 name (nameIn),
229 obj(objIn),
230 mergeMethod(nullptr)
231{
232
233 //Some sanity checks:
234 if (!objIn) {
235 std::cout << "ERROR while adding " << nameIn << ": Histogram pointer is NULL" << std::endl;
236 return;
237 }
238
239 char howToMerge[256]={};
240 char mdName[256]={};
241 strcpy(howToMerge,"<default>");
242 if (!md) {
243 std::cout << "ERROR while adding " << nameIn << ": No metadata tree. Use default merging method" << std::endl;
244 }
245 else {
246 md->SetBranchAddress("MergeMethod", howToMerge);
247 md->SetBranchAddress("Name", mdName);
248 unsigned nEntries = md->GetEntries();
249 for (unsigned i=0;i<nEntries;++i) {
250 md->GetEntry(i);
251 if (name.compare(mdName)==0) break;
252 }
253 }
254
255 if (dbg) std::cout << "Name:" << mdName << " mergeMethod=" << howToMerge << std::endl;
256 if (nullptr!=dynamic_cast<TH1*>(obj)) {
257 if (!strcmp(howToMerge,"<default>"))
259 else if (!strcmp(howToMerge,"weightedAverage"))
260 mergeMethod=&weightedAverageTH1;
261 else if (!strcmp(howToMerge,"weightedEff"))
262 mergeMethod=&weightedEff;
263 else if (!strcmp(howToMerge,"mergeRMS"))
264 mergeMethod=&mergeRMS;
265 else if (!strcmp(howToMerge,"RMSpercentDeviation"))
266 mergeMethod=&RMSpercentDeviation;
267 else if (!strcmp(howToMerge,"perBinEffPerCent"))
268 mergeMethod=&perBinEffPerCent;
269 else if (!strcmp(howToMerge,"lowerLB"))
270 mergeMethod=&lowerLB;
271 else if (!strcmp(howToMerge,"identical"))
272 mergeMethod=&identical;
273
274 else {
275 std::cout << "ERROR: Unknown merging method (" << howToMerge << ") for object of type TH1 named " << nameIn << std::endl;
276 obj=nullptr;
277 }
278 }// end if TH1
279 else if (nullptr!=dynamic_cast<TH2*>(obj)) {
280 if (!strcmp(howToMerge,"<default>"))
282 else if (!strcmp(howToMerge,"weightedAverage"))
283 mergeMethod=&weightedAverageTH2;
284 else {
285 std::cout << "ERROR: Unknown merging method (" << howToMerge << ") for object of type TH2 named " << nameIn << std::endl;
286 obj=nullptr;
287 }
288
289 }// end if TH2
290 else {
291 std::cout << "Object "<< name << " has unkown type" << std::endl;
292 obj=nullptr;
293 }
294}
295
296
297void histCollection::addDirectory(TDirectory* dir, const std::string& dirName) {
298 TIter next( dir->GetListOfKeys() );
299 TKey* key;
300 while((key=(TKey*)next())) {
301 const char* name=key->GetName();
302 const char* classname=key->GetClassName();
303 if (m_dbg) std::cout << "Found name " << name << ", classname=" << classname << std::endl;
304 const std::string newName=dirName+"/"+name;
305
306 if (this->isExcluded(newName)) {
307 std::cout << "Path " << newName << " excluded" << std::endl;
308 return;
309 }
310
311 if (!strncmp(classname,"TH1",3) || !strncmp(classname,"TH2",3) || !strncmp(classname,"TProfile",8)) {
312 auto mIt=m_data.find("dirName");
313
314 if (mIt==m_data.end()) { // New top-level directory
315 TTree* md=(TTree*)dir->Get("metadata");
316 if (!md) std::cout << "ERROR: Did not find metadata tree in directroy " << dirName << std::endl;
317 mIt=m_data.insert(std::make_pair(dirName,histDir_t(md))).first;
318 }
319 histPerDir_t histo(name,key->ReadObj(),mIt->second.md,m_dbg);
320
321 // Check if we already have this histogram in the list
322 bool found = 0;
323 for (auto it1=mIt->second.histos.begin(); it1!=mIt->second.histos.end();++it1) {
324 if( it1->name == name){
325 found=1;
326 break;
327 }
328 }
329 if ( found == 0 ){ // Add the histrogam if we didn't already have it
330 mIt->second.histos.push_back(std::move(histo));
331 }
332
333 }
334 else if (!strncmp(classname,"TDirectory",10)) {
335 TObject* obj = key->ReadObj();
336 TDirectory* subdir = dynamic_cast<TDirectory*>( obj );
337 if (subdir) {
338 this->addDirectory(subdir,newName);
339 }
340 }
341 else if (!strcmp(classname,"TTree") && (!strcmp(name,"metadata"))) {
342 //std::cout << "Found Metadata tree" << std::endl;
343 }
344 else {
345 std::cout << "Ignored objects '" << name << "' of type "<< classname << std::endl;
346 }
347 }
348 return;
349}
350
351
352void histCollection::addFile(TFile* in) {
353 auto it=m_data.begin();
354 auto it_e=m_data.end();
355 for(;it!=it_e;++it) {
356 const std::string& dirName=it->first;
357 const histDir_t& hd=it->second;
358 std::vector<histPerDir_t>::const_iterator it1=hd.histos.begin();
359 std::vector<histPerDir_t>::const_iterator it1_e=hd.histos.end();
360 for (;it1!=it1_e;++it1) {
361 const std::string fullName=dirName+"/"+it1->name;
362 if (!it1->obj) {
363 std::cout << "Object " << fullName << " not properly set up. Not merged." << std::endl;
364 continue;
365 }
366 TObject* obj=in->Get(fullName.c_str());
367 if (!obj) {
368 std::cout << "ERROR: Could not access path " << fullName <<" in file " << in->GetName() << std::endl;
369 }
370 else
371 (*it1->mergeMethod)(it1->obj,obj);
372 }//End loop over histograms in directory
373 }//End loop over directory names
374 return;
375}
376
377void histCollection::write(TFile* out) {
378 unsigned nWritten=0;
379 unsigned nIgnored=0;
380 TDirectory* histDir=nullptr;
381 std::string lastDir;
382 auto it=m_data.begin();
383 auto it_e=m_data.end();
384 for(;it!=it_e;++it) {
385 const std::string fulldir=it->first + "/";
386 //Create dirs if necessary
387 std::string::size_type j=0,j1=0;
388 while (j1!=std::string::npos) {
389 do {
390 j=j1+1;
391 j1=fulldir.find('/',j);
392 //std::cout << "Inner loop " << fulldir.substr(0,j1) << " << ==? " << lastDir.substr(0,j1) << std::endl;
393 }
394 while(j1!=std::string::npos && !fulldir.compare(0,j1,lastDir,0,j1));
395 const std::string currDirAtLevel(fulldir.substr(j,j1-j));
396 const std::string currFullDir(fulldir.substr(0,j1));
397 const std::string currBaseDir(fulldir.substr(0,j));
398 //std::cout << "Working on dir " << fulldir << " [" << currFullDir << " " << currBaseDir << " " << currDirAtLevel << std::endl;
399 lastDir=std::move(currFullDir);
400 out->cd(currBaseDir.c_str());
401 gDirectory->mkdir(currDirAtLevel.c_str());
402 }//End outer while loop - full directory created
403 //std::cout << "Done creating " << fulldir << std::endl;
404 out->cd(fulldir.c_str());
405 it->second.md->SetDirectory(histDir);
406 it->second.md->Write(nullptr,TObject::kOverwrite);
407 std::vector<histPerDir_t>::const_iterator ith=it->second.histos.begin();
408 std::vector<histPerDir_t>::const_iterator ith_e=it->second.histos.end();
409 for (;ith!=ith_e;++ith) {
410 if (ith->obj) {
411 ith->obj->Write();
412 std::cout << "Writing " << ith->name << " to dir " << fulldir << std::endl;
413 ++nWritten;
414 }
415 else {
416 std::cout << "NOT writing " << ith->name << ". Invalid." << std::endl;
417 ++nIgnored;
418 }
419 }//End loop over histograms in one directory
420 }//End loop over directories;
421 std::cout << "Wrote " << nWritten << " histograms to output file.";
422 if (nIgnored)
423 std::cout << " Omitting " << nIgnored << " histograms." << std::endl;
424 else
425 std::cout << std::endl;
426 return;
427}
428
429std::vector<std::string> splitString(const std::string& in, std::string_view delim) {
430 std::vector<std::string> retvec;
431 size_t pos1=0,pos2=0;
432 while (pos2!=std::string::npos) {
433 pos2=in.find_first_of(delim,pos1);
434 const std::string sub=in.substr(pos1,pos2-pos1);
435 if (!sub.empty())
436 retvec.push_back(std::move(sub));
437 pos1=pos2+1;
438 }
439 return retvec;
440}
441
442bool readFromTextFile(const char* filename, std::vector<std::string>& out) {
443 std::ifstream ifs (filename, std::ifstream::in );
444 if (!ifs.good()) {
445 std::cout << "Failed to open file " << filename << " for reading." << std::endl;
446 return false;
447 }
448 while (ifs.good()) {
449 std::string line;
450 getline(ifs,line);
451 //Bit of cleaning and splitting:
452 const std::vector<std::string> linetok=splitString(line," ,;\t\n");
453 std::vector<std::string>::const_iterator it=linetok.begin();
454 std::vector<std::string>::const_iterator it_e=linetok.end();
455 for(;it!=it_e;++it) {
456 if ((*it)[0]=='#') break; //ingore all characters behind '#'
457 out.push_back(*it);
458 }
459 //if (!line.size()) continue;
460 //out.push_back(line);
461 }
462 ifs.close();
463 return true;
464}
465
466// =================================================================================================
467int main(int argc, char** argv) {
468
469 if (argc<2 || (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help")))) {
470 std::cout << "Syntax:\n" << argv[0] << " [-v ] [-i inputTextFile] [-d directroy] <outfile> <infile1> <infile2> .... " << std::endl;
471 std::cout << " -v verbose " << std::endl;
472 return -1;
473 }
474
475 bool debug=false;
476 std::string outFileName;
477 std::vector<std::string> inFileNames;
478 std::vector<std::string> baseDirs;
479
480 for(int iArg=1;iArg<argc;++iArg) {
481 if (!strcmp(argv[iArg],"-v")) {
482 debug=true;
483 continue;
484 }
485
486 if (!strcmp(argv[iArg],"-d")) {
487 ++iArg;
488 if (argc<=iArg) {
489 std::cout << "ERROR: Expected a parameter (directory name) after '-d'" << std::endl;
490 return -1;
491 }
492 baseDirs.push_back(std::string(argv[iArg]));
493 continue;
494 }
495
496
497 if (!strcmp(argv[iArg],"-i")) {
498 ++iArg;
499 if (argc<=iArg) {
500 std::cout << "ERROR: Expected text file name after '-i'" << std::endl;
501 return -1;
502 }
503 readFromTextFile(argv[iArg],inFileNames);
504 continue;
505 }
506 if (outFileName.empty())
507 outFileName=argv[iArg];
508 else
509 inFileNames.push_back(std::string(argv[iArg]));
510 }//end loop over arguments
511
512
513 if (outFileName.empty()) {
514 std::cout << "ERROR: No output file name given!" << std::endl;
515 return -1;
516 }
517
518 if (!gSystem->AccessPathName(outFileName.c_str())) {
519 std::cout << "ERROR: Output file " << outFileName << " exists already!" << std::endl;
520 return -1;
521 }
522
523 if (inFileNames.empty()) {
524 std::cout << "WARNING: No input files given! Will produce empty output file" << std::endl;
525 }
526
527
528 std::cout << "Number of input files: " << inFileNames.size() << std::endl;
529 std::cout << "Output file: " << outFileName << std::endl;
530
531 if (baseDirs.empty()) {
532 baseDirs.push_back("LAr");
533 baseDirs.push_back("CaloMonitoring/LArCellMon_NoTrigSel");
534 baseDirs.push_back("CaloTopoClusters/CalBAR");
535 baseDirs.push_back("CaloTopoClusters/CalECA");
536 baseDirs.push_back("CaloTopoClusters/CalECC");
537 baseDirs.push_back("CaloTopoClusters/CalEMBAR");
538 baseDirs.push_back("CaloTopoClusters/CalEMECA");
539 baseDirs.push_back("CaloTopoClusters/CalEMECC");
540
541 }
542 else {
543 //clean superfluous slash characters
544 for (size_t i=0;i<baseDirs.size();++i) {
545 const std::vector<std::string> & dirtok=splitString(baseDirs[i],"/");
546 if (dirtok.empty()) {
547 baseDirs[i].clear();
548 continue;
549 }
550 baseDirs[i]=dirtok[0];
551 for (size_t j=1;j<dirtok.size();++j) {
552 baseDirs[i]+="/"+dirtok[j];
553 }//eld loop over dir tokens
554 }//end loop over directories
555 }
556
557 // Keeping track of which directories we found
558 std::vector<std::string> foundDirs;
559
560 histCollection listOfHists(debug);
561 listOfHists.addExclusion("/CaloMonitoring/LArCellMon_NoTrigSel/Sporadic");
562
563 TFile* in1=nullptr;
564 std::string runDir("/");
565 size_t fileIndex=0;
566 unsigned nSkippedFiles=0;
567
568 const size_t nFiles=inFileNames.size();
569
570 //Loop to find the first non-empty file
571 //for (;fileIndex<nFiles && runDir.size()==1;++fileIndex) {
572 for (;fileIndex<nFiles && foundDirs.size()!=baseDirs.size() ;++fileIndex) {
573 //in1=TFile::Open(inFileNames[fileIndex].c_str(),"READ");
574 in1=openWithRetry(inFileNames[fileIndex].c_str());
575 if (!in1) {
576 std::cout << "ERROR: Could not open first file " << inFileNames[fileIndex] << "after all attempts" << std::endl;
577 if (nSkippedFiles>MAXSKIPPEDFILES) {
578 std::cout << "Failed to read " << nSkippedFiles << " input files. Abort job ..." << std::endl;
579 return -1;
580 }
581 if (nSkippedFiles>nFiles*MAXSKIPPEDFILESFRACTION) {
582 std::cout << "Failed to read " << 100.0*nSkippedFiles/nFiles << "% of input files. Abort job ..." << std::endl;
583 return -1;
584 }
585 ++nSkippedFiles;
586 std::cout << "Continue without this file. Skipped " << nSkippedFiles << " input files so far." << std::endl;
587 continue;
588 }
589
590 std::cout << "First loop: Working on file " << inFileNames[fileIndex] <<std::endl;
591 //Get run_XXXX directory name
592 TIter next(in1->GetListOfKeys() );
593 TKey* key;
594 while((key=(TKey*)next())) {
595 const char* name=key->GetName();
596 if (!strncmp(name,"run_",4)) {
597 if (runDir.size()>1) {
598 std::cout << "ERROR More than one run_XXX directory found! Ignoring " << name << std::endl;
599 }
600 else
601 runDir.append(name);
602 }
603 }
604
605 if (runDir.size()==1) {
606 std::cout << "WARNING: No run_XXXX directory found. Empty File? Ignored." << std::endl;
607 in1->Close();
608 continue;
609 }
610
611 //Collect histogram directories
612 std::vector<std::string>::const_iterator dIt=baseDirs.begin();
613 std::vector<std::string>::const_iterator dIt_e=baseDirs.end();
614
615 for (;dIt!=dIt_e;++dIt) {
616 std::string dirName=runDir+"/"+(*dIt);
617 // In case we are looping over more files to find the directory
618
619 TDirectory* dir=dynamic_cast<TDirectory*>(in1->Get(dirName.c_str()));
620 if (!dir) {
621 std::cout << "Did not find directory " << dirName <<" in file "<<inFileNames[fileIndex].c_str()<<" !" << std::endl;
622 continue;
623 }
624 if (std::find(foundDirs.begin(), foundDirs.end(), dirName) != foundDirs.end())
625 {
626 std::cout<<"Already found "<<dirName<<" before"<<std::endl;
627 //continue;
628 }else{
629 foundDirs.push_back(dirName);
630 }
631 if (debug) std::cout << "Found directory " << dirName <<" in file "<<inFileNames[fileIndex].c_str()<<" !" << std::endl;
632 listOfHists.addDirectory(dir,dirName);
633 }
634
635 std::cout << "Number of directories: " << listOfHists.size() << std::endl;
636 std::cout<<"SIZE "<< listOfHists.size() <<std::endl;
637
638 if (debug) listOfHists.print();
639
640 //std::cout << "Closing first file" << std::endl;
641 //in1->Close("R");
642 //delete in1;
643 }//end loop to find first non-empty file
644
645 for (;fileIndex<nFiles;++fileIndex) { // Loop over remaining files
646 const char* filename=inFileNames[fileIndex].c_str();
647 //TFile* in=TFile::Open(filename,"READ");
648 TFile* in=openWithRetry(filename);
649 if (!in) {
650 std::cout << "ERROR: Could not open file " << filename << "after all attempts" << std::endl;
651 if (nSkippedFiles>MAXSKIPPEDFILES) {
652 std::cout << "Failed to read " << nSkippedFiles << " input files. Abort job ..." << std::endl;
653 return -1;
654 }
655 if (nSkippedFiles>nFiles*MAXSKIPPEDFILESFRACTION) {
656 std::cout << "Failed to read " << 100.0*nSkippedFiles/nFiles << "% of input files. Abort job ..." << std::endl;
657 return -1;
658 }
659 ++nSkippedFiles;
660 std::cout << "Continue without this file. Skipped " << nSkippedFiles << " input files so far." << std::endl;
661 continue;
662 }
663 std::cout << "Working on file " << filename << std::endl;
664 TObject* dirObj=in->Get(runDir.c_str()+1);
665 if (!dirObj) {
666 std::cout << "Directory " << runDir << " not found. Ignoring apprently empty file" << std::endl;
667 }
668 else
669 listOfHists.addFile(in);
670 in->Close();
671 delete in;
672 }
673
674 TFile* out=new TFile(outFileName.c_str(),"NEW");
675 if (!out || !out->IsOpen()) {
676 std::cout << "ERROR: Failed to open output file " << outFileName << " for writing" << std::endl;
677 return -1;
678 }
679 listOfHists.write(out);
680 out->Close();
681 delete out;
682
683 if (in1 && in1->IsOpen()) {
684 in1->Close();
685 delete in1;
686 }
687
688 if (nSkippedFiles>0) {
689 std::cout << "WARNING: Skipped " << nSkippedFiles << " input file(s)." << std::endl;
690 }
691
692 return 0;
693}
static Double_t a
void defaultMerge(TObject *a, const TObject *b)
const int MAXSKIPPEDFILES
std::vector< std::string > splitString(const std::string &in, std::string_view delim)
TFile * openWithRetry(const char *path, const unsigned nTrys=3)
bool readFromTextFile(const char *filename, std::vector< std::string > &out)
const float MAXSKIPPEDFILESFRACTION
const bool debug
Define macros for attributes used to control the static checker.
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
static void merge_identical(TH1 &a, const TH1 &b)
static void merge_weightedAverage(TH1 &a, const TH1 &b)
static void merge_RMS(TH1 &a, const TH1 &b)
static void merge_RMSpercentDeviation(TH1 &a, const TH1 &b)
static void merge_weightedAverage2D(TH2 &a, const TH2 &b)
static void merge_lowerLB(TH1 &a, const TH1 &b)
static void merge_weightedEff(TH1 &a, const TH1 &b)
static void merge_perBinEffPerCent(TH1 &a, const TH1 &b)
void(* mergeMethod)(TObject *a, const TObject *b)
histPerDir_t(const std::string &nameIn, TObject *objIn, TTree *md, bool dbg=false)
std::vector< std::string > m_exclusion
void addExclusion(const std::string &dir)
bool isExcluded(const std::string &dir)
void addFile(TFile *in)
void addDirectory(TDirectory *dir, const std::string &dirName)
void write(TFile *out)
histCollection(bool debug=false)
std::map< std::string, histDir_t, std::less<> > m_data
int main()
Definition hello.cxx:18
bool identical
std::vector< histPerDir_t > histos