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