ATLAS Offline Software
MonitoringFile.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
8 
9 #include <cmath>
10 #include <cstdio>
11 #include <exception>
12 #include <fstream>
13 #include <iostream>
14 #include <memory>
15 #include <set>
16 #include <sstream>
17 #include <vector>
18 #include <map>
19 #include <ctime>
20 #include <format>
21 #include <boost/algorithm/string/split.hpp>
22 #include <boost/algorithm/string/classification.hpp>
23 #include <boost/lexical_cast.hpp>
24 #include <regex>
25 #include <TObject.h>
26 #include <TSystem.h>
27 
28 #include <TDirectory.h>
29 #include <TFile.h>
30 #include <TGraph.h>
31 #include <TH1.h>
32 #include <TH2.h>
33 #include <TIterator.h>
34 #include <TKey.h>
35 #include <TROOT.h>
36 #include <TTree.h>
37 #include <TEfficiency.h>
38 #include "TTreeReader.h"
39 #include "TTreeReaderArray.h"
40 
42 
43 
44 namespace dqutils {
45 
46 bool histOKToMerge(TH1* h) {
47  Long_t arrsize, computedsize;
48  switch (h->GetDimension()) {
49  case 1:
50  computedsize = h->GetNbinsX()+2;
51  break;
52  case 2:
53  computedsize = (h->GetNbinsX()+2)*(h->GetNbinsY()+2);
54  break;
55  case 3:
56  computedsize = (h->GetNbinsX()+2)*(h->GetNbinsY()+2)*(h->GetNbinsZ()+2);
57  break;
58  default:
59  std::cerr << "Unable to handle dimension of " << h->GetName() << "; refusing to merge";
60  return false;
61  }
62  TArray* arrptr = dynamic_cast<TArray*>(h);
63  if (! arrptr) {
64  std::cerr << "Unable to cast TH1 to TArray for " << h->GetName() << " - saying it's OK and hoping for the best" << std::endl;
65  return true;
66  }
67  arrsize = arrptr->GetSize();
68  if (computedsize != arrsize) {
69  std::cout << "Sizes: computed " << computedsize << " array " << arrsize << std::endl;
70  }
71  return computedsize == arrsize;
72 }
73 
74 // *********************************************************************
75 // Public Methods
76 // *********************************************************************
77 
79 OutputMetadata( TTree* metadata )
80  : m_metadata(metadata)
81 {
82  makeBranch( "Name", "Name/C" );
83  makeBranch( "Interval", "Interval/C" );
84  makeBranch( "TriggerChain", "TriggerChain/C" );
85  makeBranch( "MergeMethod", "MergeMethod/C" );
86 }
87 
88 void
90 makeBranch(const char* branchName, const char* branchstr)
91 {
92  if (!m_metadata->GetBranch(branchName)) {
93  m_metadata->Branch(branchName, (void*) nullptr, branchstr);
94  }
95 }
96 
97 void
99 fill( const std::string & theName,
100  const std::string & theInterval,
101  const std::string & theChain,
102  const std::string & theMerge )
103 {
104  std::string name=theName;
105  std::string interval = theInterval;
106  std::string chain = theChain;
107  std::string merge = theMerge;
108  m_metadata->SetBranchAddress("Name", name.data());
109  m_metadata->SetBranchAddress("Interval", interval.data());
110  m_metadata->SetBranchAddress("TriggerChain", chain.data());
111  m_metadata->SetBranchAddress("MergeMethod", merge.data());
112  m_metadata->Fill();
113 }
114 
115 
120 {
121  m_debugLevel=0;
123  m_doTiming=false;
125 }
126 
127 
129 MonitoringFile( const std::string & fileName )
132 {
133  m_debugLevel=0;
135  m_doTiming=false;
138 }
139 
140 
143 {
145 
146  delete m_file;
147  delete m_mergeMatchDirRE;
148  delete m_mergeMatchHistoRE;
149 }
150 
151 bool MonitoringFile::setHistogramRegEx(const std::string& re){
152  if(re.empty()){
153  std::cerr<<__PRETTY_FUNCTION__<<"Warning empty regular expression string is given. Old RegEx \""<<m_mergeMatchHistoREString<<"\" is not changed"<<std::endl;
154  std::cerr<<__PRETTY_FUNCTION__<<"See http://www.boost.org/doc/libs/1_42_0/libs/regex/doc/html/boost_regex/syntax.html for allowed regular expression syntax"<<std::endl;
155  return false;
156  }
157  std::regex *reNew=0;
158  try{
159  reNew=new std::regex(re);
160  // this should fail if there are any problems with re!
161  std::string test("Test String");
162  std::regex_match(test,*reNew);
163  }catch(std::exception& e){
164  std::cerr<<__PRETTY_FUNCTION__<<"Invalid RegEx string \""<<re<<"\". Old RegEx \""<<m_mergeMatchHistoREString<<"\" is not changed"<<std::endl;
165  std::cerr<<__PRETTY_FUNCTION__<<"See http://www.boost.org/doc/libs/1_42_0/libs/regex/doc/html/boost_regex/syntax.html for allowed regular expression syntax"<<std::endl;
166  delete reNew;
167  return false;
168  }
169  delete m_mergeMatchHistoRE;
171  m_mergeMatchHistoRE=reNew;
172  //delete reNew;
173  m_useRE=true;
174  return true;
175 }
176 
177 bool MonitoringFile::setDirectoryRegEx(const std::string& re){
178  if(re.empty()){
179  std::cerr<<__PRETTY_FUNCTION__<<"Warning empty regular expression string is given. Old RegEx \""<<m_mergeMatchDirREString<<"\" is not changed"<<std::endl;
180  std::cerr<<__PRETTY_FUNCTION__<<"See http://www.boost.org/doc/libs/1_42_0/libs/regex/doc/html/boost_regex/syntax.html for allowed regular expression syntax"<<std::endl;
181  return false;
182  }
183  std::regex *reNew=0;
184  try{
185  reNew=new std::regex(re);
186  std::regex_match("Test string",*reNew);
187  }catch(std::exception& e){
188  std::cerr<<__PRETTY_FUNCTION__<<"Invalid RegEx string \""<<re<<"\". Old RegEx \""<<m_mergeMatchDirREString<<"\" is not changed"<<std::endl;
189  std::cerr<<__PRETTY_FUNCTION__<<"See http://www.boost.org/doc/libs/1_42_0/libs/regex/doc/html/boost_regex/syntax.html for allowed regular expression syntax"<<std::endl;
190  delete reNew;
191  return false;
192  }
193  delete m_mergeMatchDirRE;
195  m_mergeMatchDirRE=reNew;
196  //delete reNew;
197  m_useRE=true;
198  return true;
199 }
200 
201 void
203 getAllDirs( DirMap_t& dirmap, TDirectory* dir, const std::string & dirName )
204 {
205  if( dir == 0 )
206  return;
207 
208  if( dirName != "" ) {
209  DirMap_t::value_type dirmapVal( dirName, dir );
210  dirmap.insert( dirmapVal );
211  }
212 
213  TIter next( dir->GetListOfKeys() );
214  TKey* key;
215  while( (key = dynamic_cast<TKey*>( next() )) != 0 ) {
216  // don't delete TDirectories
217  TObject* obj = key->ReadObj();
218  TDirectory* subdir = dynamic_cast<TDirectory*>( obj );
219  if( subdir != 0 ) {
220  std::string subdirName( subdir->GetName() );
221  std::string fName("");
222  if( dirName != "" ) {
223  fName += dirName;
224  fName += '/';
225  }
226  fName += subdirName;
227  getAllDirs( dirmap, subdir, fName );
228  }
229  else {
230  delete obj;
231  }
232  }
233 }
234 
235 
236 TDirectory*
238 createDir( DirMap_t& dirmap, TDirectory* dir, const std::string &parent, const std::string & path )
239 {
240  if( dir == 0 )
241  return 0;
242 
243  TDirectory* subdir(0);
244  DirMap_t::const_iterator diter;
245  std::string::size_type i = path.find_first_of('/');
246  std::string fName("");
247  if( parent != "" ) {
248  fName += parent;
249  fName += '/';
250  }
251 
252  if( i != std::string::npos ) {
253  std::string dName( path, 0, i );
254  std::string pName( path, i+1, std::string::npos );
255  fName += dName;
256  if( dName != "" ) {
257  diter = dirmap.find( fName );
258  if( diter != dirmap.end() ) {
259  subdir = diter->second;
260  }
261  else {
262  subdir = dir->mkdir( dName.c_str() );
263  DirMap_t::value_type dirmapVal( fName, subdir );
264  dirmap.insert( dirmapVal );
265  }
266  }
267  else {
268  subdir = dir;
269  }
270  return createDir( dirmap, subdir, fName, pName );
271  }
272 
273  fName += path;
274 
275  diter = dirmap.find( fName );
276  if( diter != dirmap.end() ) {
277  return diter->second;
278  }
279 
280  subdir = dir->mkdir( path.c_str() );
281  DirMap_t::value_type dirmapVal( fName, subdir );
282  dirmap.insert( dirmapVal );
283  return subdir;
284 }
285 
286 
287 TKey*
289 getObjKey( TDirectory* dir, const std::string & path )
290 {
291  if( dir == 0 )
292  return 0;
293 
294  TKey* key(0);
295 
296  std::string::size_type i = path.find_first_of('/');
297  if( i != std::string::npos ) {
298  std::string dName( path, 0, i );
299  std::string pName( path, i+1, std::string::npos );
300  if( dName != "" ) {
301  key = dir->FindKey( dName.c_str() );
302  if( key != 0 ) {
303  TDirectory* subDir = dynamic_cast<TDirectory*>( key->ReadObj() );
304  if (subDir) {
305  return getObjKey( subDir, pName );
306  } // else fall through
307  }
308  return 0;
309  }
310  return getObjKey( dir, pName );
311  }
312 
313  return dir->FindKey( path.c_str() );
314 
315 }
316 
317 std::string getInputDirectory(const std::string & outputDirName, TFile* input, bool has_multiple_runs, std::map< TFile*, std::string >* prefixes) {
318  if (! has_multiple_runs) {
319  return outputDirName;
320  } else {
321  std::string retval(outputDirName);
322  std::string::size_type sepi = retval.find("run_multiple");
323  if (sepi != std::string::npos && prefixes->find(input) != prefixes->end()) {
324  retval.replace(sepi, 12, (*prefixes)[input]);
325  }
326  return retval;
327  }
328 }
329 
330 std::string getOutputDirectory(const std::string & inputDirName, TFile* input, bool has_multiple_runs, std::map< TFile*, std::string >* prefixes) {
331  if (! has_multiple_runs) {
332  return inputDirName;
333  } else {
334  std::string retval(inputDirName);
335  if (prefixes->find(input) == prefixes->end()) {
336  return retval;
337  }
338  std::string::size_type sepi = retval.find((*prefixes)[input]);
339  if (sepi != std::string::npos) {
340  retval.replace(sepi, (*prefixes)[input].length(), "run_multiple");
341  }
342  return retval;
343  }
344 }
345 
346 std::string getOutputDirectory(TKey* key, TFile* input, bool has_multiple_runs, std::map< TFile*, std::string >* prefixes) {
347  if (TClass::GetClass(key->GetClassName())->InheritsFrom("TDirectory")) {
348  return getOutputDirectory(key->GetName(), input, has_multiple_runs, prefixes);
349  } else {
350  return key->GetName();
351  }
352 }
353 
354 // This function will populate a mapping between key names and vectors of cycles
355 void populateKeyMapping(TDirectory* dir, keycyclemap& kcmap) {
356  TIter nextKey( dir->GetListOfKeys() );
357  TKey* key;
358  std::string keyName("");
359  while( (key = dynamic_cast<TKey*>( nextKey() )) != 0 ) {
360  kcmap[key->GetName()].push_back(key->GetCycle());
361  }
362 }
363 
364 // This function will merge objects given a name, a vector of cycles,
365 // a directory, a merge type, and optionally an object to merge into.
366 // Return value is a merged object.
367 void MonitoringFile::mergeObjsMultiCycles(const std::string& keyname,
368  const std::vector<int>& cycles,
369  TDirectory* dir,
370  const std::string & mergeType,
371  std::unique_ptr<TObject>& obj) {
372  if (cycles.size() == 0) {
373  return;
374  }
375  int start_idx = 0;
376  if (obj == nullptr) {
377  TKey* key(dir->GetKey(keyname.c_str(), cycles[0]));
378  obj.reset(key->ReadObj());
379  start_idx = 1;
380  TH1* h = dynamic_cast<TH1*>(obj.get());
381  if (h && !histOKToMerge(h)) {
382  // histogram is damaged goods
383  std::cerr << "WARNING: HISTOGRAM " << h->GetName() << " IS INTERNALLY INCONSISTENT, NOT MERGING" << std::endl;
384  return;
385  }
386  }
387  for (std::vector<int>::size_type idx = start_idx;
388  idx < cycles.size(); ++idx) {
389  TKey* nextKey = dir->GetKey(keyname.c_str(), cycles[idx]);
390  if (nextKey != 0) {
391  std::unique_ptr<TObject> nextObj(nextKey->ReadObj());
392  if (nextObj.get() == 0) {
393  std::cerr << "MonitoringFile::mergeObjsMultiCycles(): "
394  << "In directory \"" << dir->GetPath() << "\",\n"
395  << " Object \"" << keyname << "\" cannot be read from file: skipping\n";
396  continue;
397  }
398  TH1* h = dynamic_cast<TH1*>(nextObj.get());
399  if (h && !histOKToMerge(h)) {
400  // histogram is damaged goods; even deleting it may be dangerous
401  std::cerr << "WARNING: HISTOGRAM " << h->GetName() << " IS INTERNALLY INCONSISTENT, NOT MERGING" << std::endl;
402  (void)nextObj.release();
403  continue;
404  }
405  // next: if current "target" histogram exists, but is empty, reset it to the next object.
406  // works around
407  h = dynamic_cast<TH1*>(obj.get());
408  if (h && h->GetEntries() == 0 && h->GetSumOfWeights() == 0) {
409  // just take over nextObj as obj
410  obj.reset(nextObj.release());
411  continue;
412  }
413  if (h && (obj->IsA() != h->IsA())) {
414  // problem: class types have changed ...
415  std::cerr << "WARNING: CHANGE OF CLASS TYPES FOR " << h->GetName() << ", NOT MERGING" << std::endl;
416  continue;
417  }
418  MonitoringFile::mergeObjs(obj.get(), nextObj.get(), mergeType,m_debugLevel>VERBOSE?VERBOSE: (dqutils::MonitoringFile::debugLevel_t)m_debugLevel.load(),std::string(dir->GetPath()));
419  } else {
420  std::cerr << "MonitoringFile::mergeObjsMultiCycles(): NULL KEY; corrupt file?" << std::endl;
421  }
422  }
423  return;
424 }
425 
426 
427 void getListOfKeysWithName(TDirectory* dir, const std::string& keyname,
428  TCollection* target)
429 {
430  target->Clear();
431  TIter keyit(dir->GetListOfKeys());
432  TKey* key;
433  while ( (key = dynamic_cast<TKey*>(keyit())) != 0 ) {
434  if (keyname == key->GetName()) {
435  target->Add(key);
436  }
437  }
438 }
439 
440 void populateCycleVector(const TCollection& source, std::vector<int>& target)
441 {
442  TKey* key;
443  TIter keyit(&source);
444  while ( (key = dynamic_cast<TKey*>(keyit())) != 0 ) {
445  target.push_back(key->GetCycle());
446  }
447 }
448 
449 
450 // 'mergeDirectory(...)' is based on 'MergeRootfile(...)' in the hadd.cxx utility in ROOT, using
451 // the same algorithm for looping over files, directories and histograms.
452 
453 void
455 mergeDirectory( TDirectory* outputDir, const std::vector<TFile*>& inputFiles, bool has_multiple_runs, std::map< TFile*, std::string >* prefixes )
456 {
457  typedef std::set< std::string > ObjNameSet_t;
458  typedef std::map< std::string, MetaData > MetaDataMap_t;
459 
460  if( outputDir == 0 ) {
461  return;
462  }
463 
464  gROOT->cd();
465 
466  std::string outputDirPath( outputDir->GetPath() );
467  std::string outputDirName( outputDirPath );
468  std::string::size_type sepi = outputDirPath.find_last_of(':');
469  if( sepi != std::string::npos ) {
470  outputDirName = std::string( outputDirPath, sepi+2, std::string::npos );
471  }
472  //std::cout << outputDirName << std::endl;
473  bool metadataInDir = false;
474  bool targetDir=!m_useRE;
475  if(m_useRE && (std::regex_search(outputDirName,*m_mergeMatchDirRE))){
476  //std::cout<<"Found target dir \""<<outputDirName<<"\""<<std::endl;
477  targetDir=true;
478  }
479  TTree* mdTree = new TTree( "metadata", "Monitoring Metadata" );
480  mdTree->SetDirectory(0);
481  OutputMetadata outputmd( mdTree );
482 
483  ObjNameSet_t mergedObjs;
484  MetaDataMap_t mdMap;
485 
486  std::vector<TFile*>::const_iterator inputFilesEnd = inputFiles.end();
487  for( std::vector<TFile*>::const_iterator i = inputFiles.begin(); i != inputFilesEnd; ++i ) {
488  TFile* inputFile = *i;
489  TDirectory* inputDir = inputFile->GetDirectory( getInputDirectory(outputDirName, inputFile, has_multiple_runs, prefixes).c_str() );
490  if( inputDir == 0 ) {
491  // Directory is not present in this file; try next file
492  continue;
493  }
494  //std::cout<<"inputdir=\""<<inputDir->GetPath()<<"\""<<std::endl;
495  if( inputDir == outputDir ) {
496  continue;
497  }
498 
499  inputDir->cd();
500  fillMetaDataMap( mdMap, inputDir );
501  gROOT->cd();
502 
503  TIter nextKey( inputDir->GetListOfKeys() );
504  TKey* key;
505  std::string keyName("");
506  keycyclemap kcmap;
508 
509  for (keycyclemap::iterator kcit = kcmap.begin();
510  kcit != kcmap.end();
511  ++kcit) {
512  key = inputDir->GetKey(kcit->first.c_str(), kcit->second.back());
513  if (! key) {
514  std::cout << "Key " << kcit->first.c_str() << ";" << kcit->second.back() << " not readable" << std::endl;
515  continue;
516  }
517  kcit->second.pop_back();
518  keyName = getOutputDirectory(key, inputFile, has_multiple_runs, prefixes);
519  ObjNameSet_t::iterator obji = mergedObjs.find( keyName );
520  if( obji != mergedObjs.end() ) {
521  // Object has already been processed
522  continue;
523  }
524  // we only need to read the non-dir objects below target directory. skip the rest
525  bool isDir=false;
526  if(m_useRE && key->IsFolder()){
527  //std::cout<<"Key "<<keyName<<" is a folder"<<std::endl;
528  if(keyName!="metadata")isDir=true; //metadata is not going to be merged, treat it as a regular obj
529  }
530  if(!targetDir && !isDir){
531  //std::cerr<<"Skipping keyname "<keyname<<std::endl;
532  continue; //skip everything except directories
533  }
534  std::unique_ptr<TObject> obj(key->ReadObj());
535  if (obj.get() == 0) {
536  std::cerr << "MonitoringFile::mergeDirectory(): "
537  << "In directory \"" << inputDir->GetPath() << "\",\n"
538  << " Object \"" << key->GetName() << "\" cannot be read from file: skipping\n";
539  continue;
540  }
541 
542  // we actually have an object, and it hasn't been done before
543  mergedObjs.insert( keyName );
544 
545  TH1* h(0);
546  TGraph* g(0);
547  TEfficiency* e(0);
548  TDirectory* d(0);
549  TTree* t(0);
550  //moved inside if to speedup
551 // h = dynamic_cast<TH1*>( obj.get() );
552 // d = dynamic_cast<TDirectory*>( obj.get() );
553 // g = dynamic_cast<TGraph*>( obj.get() );
554 // t = dynamic_cast<TTree*>( obj.get() );
555 
556  //merge only objects below target directory
557  if ( (targetDir) && ( (h = dynamic_cast<TH1*>(obj.get()))
558  || (g = dynamic_cast<TGraph*>(obj.get()))
559  ||((t = dynamic_cast<TTree*>(obj.get())) && (keyName!="metadata"))
560  || (e = dynamic_cast<TEfficiency*>(obj.get()))
561  )
562  ) {
563  //skip cases where regexp doesn't match object name, all directories are processed by default
564  if(m_useRE){
565  if(!std::regex_search(keyName,*m_mergeMatchHistoRE)){
566  //std::cerr<<" skipping keyName=\""<<outputDirName+'/'+keyName<<"\""<<std::endl;
567  continue; // not the histogram we want
568  }
569  }
570  std::string mergeType("<default>");
571  MetaDataMap_t::iterator mdi = mdMap.find( keyName );
572  if( mdi != mdMap.end() ) {
573  metadataInDir = true;
574  const MetaData& md = mdi->second;
575  if (has_multiple_runs &&
576  (md.interval != "run" &&
577  md.interval != "fill" &&
578  md.interval != "all" &&
579  md.interval != "file")){
580  continue;
581  }
582  outputmd.fill( md.name, md.interval, md.chain, md.merge );
583  mergeType = md.merge;
584  if( g && (md.merge != "<default>") ) {
585  std::cerr << "MonitoringFile::mergeDirectory(): "
586  << "In directory \"" << inputDir->GetPath() << "\",\n"
587  << " TGraph \"" << keyName << "\" requests merging type " << mergeType
588  << " but only default merging implemented for TGraphs\n";
589  }
590  if( t && (md.merge != "<default>") ) {
591  std::cerr << "MonitoringFile::mergeDirectory(): "
592  << "In directory \"" << inputDir->GetPath() << "\",\n"
593  << " TTree \"" << keyName << "\" requests merging type " << mergeType
594  << " but only default merging implemented for TTrees\n";
595  }
596  if( e && (md.merge != "<default>") ) {
597  std::cerr << "MonitoringFile::mergeDirectory(): "
598  << "In directory \"" << inputDir->GetPath() << "\",\n"
599  << " TEfficiency \"" << keyName << "\" requests merging type " << mergeType
600  << " but only default merging implemented for TEfficiency\n";
601  }
602  }else {
603  std::cerr << "MonitoringFile::mergeDirectory(): "
604  << "In directory \"" << inputDir->GetPath() << "\",\n"
605  << " object \"" << keyName << "\" has no metadata\n";
606  }
607  if(t){
608  TDirectory* currentDir = gDirectory;
609  outputDir->cd();
610  TTree* t2 = t->CloneTree();
611  // this disconnects parent tree
612  obj.reset(t2);
613  currentDir->cd();
614  }
615  mergeObjsMultiCycles(keyName, kcit->second, inputDir,
616  mergeType, obj);
617  for( std::vector<TFile*>::const_iterator j = i+1; j!= inputFilesEnd; ++j ) {
618  TFile* nextInputFile = *j;
619  TDirectory* nextInputDir = nextInputFile->GetDirectory( getInputDirectory(outputDirName, *j, has_multiple_runs, prefixes).c_str() );
620  if( nextInputDir == 0 ) {
621  // Directory is not present in this file; try next file
622  continue;
623  }
624 
625  TObjArray tl; std::vector<int> nextCycles;
626  getListOfKeysWithName(nextInputDir, kcit->first, &tl);
627  populateCycleVector(tl, nextCycles);
628 
629  mergeObjsMultiCycles(kcit->first, nextCycles,
630  nextInputDir, mergeType, obj);
631 
632  }
633  outputDir->cd();
634  if ((h = dynamic_cast<TH1*>(obj.get()))) {
635  h->SetDirectory(outputDir);
636  }
637 
638  obj->Write();
639  }else if( (targetDir) && (t = dynamic_cast<TTree*>(obj.get())) ) {
640  // do not merge metadata
641  }else if((d = dynamic_cast<TDirectory*>( obj.get() ))) {
642  // Do not run the multicycle merge on directories;
643  // haven't seen one yet that has multiple keys...
644  // Merge TDirectory
645  outputDir->cd();
646  std::string outputSubDirName(getOutputDirectory(d->GetName(), inputFile, has_multiple_runs, prefixes));
647  TDirectory* outputSubDir = outputDir->mkdir( outputSubDirName.c_str(), d->GetTitle() );
648  mergeDirectory( outputSubDir, inputFiles, has_multiple_runs, prefixes );
649  }else {
650  std::cout << "MonitoringFile::mergeDirectory(): "
651  << "In directory \"" << inputDir->GetPath() << "\",\n"
652  << " Object \"" << key->GetName() << "\" will not be merged\n";
653  }
654 
655  }
656  }
657 
658  // Write metadata TTree to output directory
659  if( metadataInDir ) {
660  outputDir->cd();
661  mdTree->SetDirectory(outputDir);
662  mdTree->Write();
663  }
664  delete mdTree;
665 }
666 
667 
668 void
670 fillMetaDataMap( std::map<std::string,dqutils::MonitoringFile::MetaData>& mdMap, TDirectory* dir )
671 {
672  if (dir == 0) return;
673  TTree *md = dynamic_cast<TTree*>(dir->Get("metadata"));
674  if (md == 0) return;
675 
676  TTreeReader reader(md);
677  TTreeReaderArray<char> i_name(reader, "Name");
678  TTreeReaderArray<char> i_interval(reader, "Interval");
679  TTreeReaderArray<char> i_chain(reader, "TriggerChain");
680  TTreeReaderArray<char> i_merge(reader, "MergeMethod");
681 
682  while (reader.Next()) {
683  const std::string nameStr(static_cast<char*>(i_name.GetAddress()));
684  if( mdMap.find(nameStr) == mdMap.end() ) {
685  MetaData md( nameStr,
686  static_cast<char*>(i_interval.GetAddress()),
687  static_cast<char*>(i_chain.GetAddress()),
688  static_cast<char*>(i_merge.GetAddress()) );
689  std::map<std::string,MetaData>::value_type mdVal( nameStr, md );
690  mdMap.insert( mdVal );
691  }
692  }
693 
694  delete md;
695 }
696 
697 
698 // 'mergeFiles(...)' is based on the hadd.cxx utility distributed with ROOT
699 
700 void
702 mergeFiles( const std::string & outFileName, const std::vector<std::string>& files )
703 {
705  TH1::AddDirectory(false);
706  if(m_useRE){
707  std::cout<<" ========== Using regular expressions for selective merging ========== "<<std::endl;
708  std::cout<<" Directory selection RE=\""<<m_mergeMatchDirREString<<"\""<<std::endl;
709  std::cout<<" Object selection RE=\""<<m_mergeMatchHistoREString<<"\""<<std::endl;
710  }
711  if (m_doTiming) {
712  std::cout << "CPU time measurement activated " << std::endl;
713  }
714  typedef std::vector<TFile*> TFileList_t;
715  typedef std::map<TFile*, std::string> PrefixIgnore_t;
716 
717  std::unique_ptr<TFile> outfile( TFile::Open(outFileName.c_str(),"RECREATE",outFileName.c_str(),m_fileCompressionLevel) );
718  if( outfile.get() == 0 ) {
719  std::cerr << "MonitoringFile::mergeFiles(): "
720  << "Output file not opened\n";
721  return;
722  }
723 
724  TFileList_t tfiles;
725  PrefixIgnore_t prefix_ignore;
726 
727  std::vector< std::string >::const_iterator filesEnd = files.end();
728  std::vector< std::string >::const_iterator fi;
729  for( fi = files.begin(); fi != filesEnd; ++fi ) {
730  std::cout << "Opening file: " << *fi << "\n";
731  TFile* f = TFile::Open( fi->c_str() );
732  if( f == 0 || ! f->IsOpen()) {
733  std::cerr << "MonitoringFile::mergeFiles(): "
734  << "Input file not opened\n";
735  delete f;
736  continue;
737  }
738  TList* keys = f->GetListOfKeys();
739  if (keys->GetSize() == 0) {
740  std::cerr << "MonitoringFile::mergeFiles(): "
741  << "Input file " << *fi << " has no keys!"
742  << std::endl;
743  delete f;
744  continue;
745  }
746  std::vector< std::string > runkeys;
747  TIter keyitr(keys);
748  TKey* key;
749 
750  while ( (key = dynamic_cast<TKey*>(keyitr())) != 0 ) {
751  std::string keyname(key->GetName());
752  if (keyname.substr(0,4) == "run_") {
753  runkeys.push_back(keyname);
754  }
755  }
756  if (runkeys.size() > 1) {
757  std::cerr << "MonitoringFile::mergeFiles():\n"
758  << " Input root file " << *fi << " has multiple top-level run_* keys\n"
759  << " Assuming " << runkeys[0] << " is the run key"
760  << std::endl;
761  }
762  if (runkeys.size() > 0) {
763  prefix_ignore[f] = runkeys[0];
764  }
765  tfiles.push_back(f);
766  }
767 
768  // check to see if all run keys are the same
769  bool has_multiple_runs = false;
770  std::string prev_key_name("");
771 
772  for (PrefixIgnore_t::const_iterator pi_it = prefix_ignore.begin();
773  pi_it != prefix_ignore.end();
774  ++pi_it) {
775  if (prev_key_name != pi_it->second) {
776  if (prev_key_name == "") {
777  prev_key_name = pi_it->second;
778  } else {
779  has_multiple_runs = true;
780  break;
781  }
782  }
783  }
784 
785  if (has_multiple_runs) {
786  std::cout << "Multiple runs detected in input files.\n"
787  << "Will merge ONLY RUN, FILL, FILE, or ALL histograms to run_multiple directory.\n"
788  << "(That is, no event block, lumi block, lowStat, medStat,\n"
789  << "or higStat histograms will be in the output.)"
790  << std::endl;
791  }
792 
793  std::cout << "Writing file: " << outFileName << "\n";
794  std::cout << "\nWarning messages from merging follow:\n\n";
795  std::cout.flush();
796  mergeDirectory( outfile.get(), tfiles, has_multiple_runs, &prefix_ignore );
797 
798  outfile->Close();
799 
800  TFileList_t::const_iterator tfilesEnd = tfiles.end();
801  TFileList_t::const_iterator tfi;
802  for( tfi = tfiles.begin(); tfi != tfilesEnd; ++tfi ) {
803  TFile* tf = *tfi;
804  tf->Delete("");
805  tf->Close();
806  delete tf;
807  }
808 
809  if (m_doTiming) {
810  std::vector<std::pair<std::string,clock_t> > cpuPerHistVec;
811  std::cout << "CPU time (seconds) for histogram merging:" << std::endl;
812  for ( const auto& [name,time] : m_cpuPerHistogram) {
813  cpuPerHistVec.emplace_back(name,time);
814  }
815  auto ordering=[](const std::pair<std::string,clock_t>& a, const std::pair<std::string,clock_t>& b) {return a.second<b.second;};
816  std::sort(cpuPerHistVec.begin(),cpuPerHistVec.end(),ordering);
817 
818  for (const auto& [name,time] : cpuPerHistVec) {
819  const double tSec= double(time)/CLOCKS_PER_SEC;
820  std::cout << std::format("{:<30} : {:10.3f}",name,tSec) << std::endl;
821  }
822  }
823  std::cout << "\n";
824  std::cout << "****************************************\n\n";
825 }
826 
827 
828 void
830 mergeFiles( const std::string & outFileName, const std::string & listFileName )
831 {
832  typedef std::vector< std::string > FileList_t;
833 
834  const unsigned int nFilesAtOnce = 50;
835 
836  FileList_t allFiles;
837  bool success = setListFromFile( allFiles, listFileName );
838  if( !success ) {
839  std::cerr << "MonitoringFile::mergeFiles(): Cannot merge files\n";
840  return;
841  }
842 
843  if( allFiles.size() <= nFilesAtOnce ) {
845  return;
846  }
847 
848  FileList_t procFiles, tmpIntermediateFiles;
849 
850 
851  FileList_t::const_iterator filesEnd = allFiles.end();
852  FileList_t::const_iterator fi = allFiles.begin();
853 
854  unsigned int counter = 0;
855  std::string tmpInputFile("");
856  std::string tmpOutputFile("");
857 
858  // new logic: merge intermediately, then merge intermediate files
859  while( fi != filesEnd ) {
860 
861  procFiles.push_back(*fi);
862  ++counter; ++fi;
863  if ( counter % nFilesAtOnce == 0 || fi == filesEnd ) {
864  std::ostringstream nameStream;
865  nameStream << "tmp_merge_" << counter << ".root";
866  tmpOutputFile = nameStream.str();
867  tmpIntermediateFiles.push_back(tmpOutputFile);
868  mergeFiles( tmpOutputFile, procFiles );
869  procFiles.clear();
870  }
871  /*
872  if( counter == 0 ) {
873  tmpOutputFile = *fi;
874  }
875 
876  ++counter;
877  ++fi;
878 
879  if( counter % nFilesAtOnce == 0 || fi == filesEnd ) {
880  tmpInputFile = tmpOutputFile;
881  procFiles.push_back( tmpInputFile );
882  std::ostringstream nameStream;
883  nameStream << "tmp_merge_" << counter << ".root";
884  tmpOutputFile = nameStream.str();
885  mergeFiles( tmpOutputFile, procFiles );
886  if( counter > nFilesAtOnce ) {
887  std::remove( tmpInputFile.c_str() );
888  }
889  procFiles.clear();
890  }
891 
892  if( fi != filesEnd ) {
893  procFiles.push_back( *fi );
894  }
895  */
896  }
897 
898  /*
899  if( std::rename(tmpOutputFile.c_str(),outFileName.c_str()) == 0 ) {
900  std::cout << "Renaming " << tmpOutputFile << " as " << outFileName << "\n";
901  }
902  else {
903  std::cerr << "Cannot rename " << tmpOutputFile << " as " << outFileName << "\n";
904  }
905  */
906  mergeFiles(outFileName, tmpIntermediateFiles);
907  for (const auto& tmpFile : tmpIntermediateFiles) {
908  const bool deleteSuccessful = (std::remove(tmpFile.c_str()) == 0);
909  if (not deleteSuccessful){
910  std::cerr<<"Temporary file "<<tmpFile<<" could not be deleted.";
911  }
912  }
913 }
914 
915 
916 
917 bool
919 setFile( const std::string & fileName )
920 {
921  clearData();
922  m_file = TFile::Open( fileName.c_str() );
923  if( m_file != 0 )
924  return true;
925 
926  return false;
927 }
928 
929 
930 void
933 {
934  if( m_file == 0 ) {
935  std::cerr << "MonitoringFile::printDirectories(): "
936  << "No input file is open\n";
937  return;
938  }
939 
940  DirMap_t indirmap;
941 
942  getAllDirs( indirmap, m_file, "" );
943 
944  DirMap_t::const_iterator idirend = indirmap.end();
945  for( DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir ) {
946  std::string idirName = idir->first;
947  std::cout << idirName << "\n";
948  }
949 }
950 
951 
952 void
955 {
956  if( m_file == 0 ) {
957  std::cerr << "MonitoringFile::printStatistics(): "
958  << "No input file is open\n";
959  return;
960  }
961 
962  DirMap_t indirmap;
963 
964  getAllDirs( indirmap, m_file, "" );
965 
966  DirMap_t::const_iterator idirend = indirmap.end();
967  for( DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir ) {
968  std::string idirName = idir->first;
969 
970  GatherStatistics stat_shift( idirName );
971  GatherStatistics stat_all( idirName );
972 
973  loopOnHistogramsInMetadata( stat_shift, idir->second );
974  loopOnHistograms( stat_all, idir->second );
975 
976  std::cout.setf(std::ios_base::left,std::ios_base::adjustfield);
977  std::cout.width(80);
978  std::cout << idirName << " ";
979 
980  std::cout.setf(std::ios_base::right,std::ios_base::adjustfield);
981  std::cout << " shift: ";
982  std::cout.width(3);
983  std::cout << stat_shift.m_nHist1D << " ";
984  std::cout.width(5);
985  std::cout << stat_shift.m_nHist1DBins << " ";
986  std::cout.width(3);
987  std::cout << stat_shift.m_nHist2D << " ";
988  std::cout.width(7);
989  std::cout << stat_shift.m_nHist2DBins << " ";
990  std::cout.width(3);
991  std::cout << stat_shift.m_nGraph << " ";
992  std::cout.width(5);
993  std::cout << stat_shift.m_nGraphPoints << " ";
994 
995 
996  std::cout << " all: ";
997  std::cout.width(3);
998  std::cout << stat_all.m_nHist1D << " ";
999  std::cout.width(5);
1000  std::cout << stat_all.m_nHist1DBins << " ";
1001  std::cout.width(3);
1002  std::cout << stat_all.m_nHist2D << " ";
1003  std::cout.width(7);
1004  std::cout << stat_all.m_nHist2DBins << " ";
1005  std::cout.width(3);
1006  std::cout << stat_all.m_nGraph << " ";
1007  std::cout.width(5);
1008  std::cout << stat_all.m_nGraphPoints << "\n";
1009 
1010  std::cout << std::flush;
1011  }
1012 }
1013 
1014 
1015 bool
1017 copyHistograms( const std::string & outFileName, const std::string & dirName )
1018 {
1020  // bool useRecursiveDelete = gROOT->MustClean();
1021  // gROOT->SetMustClean(false);
1022 
1023  if( m_file == 0 ) {
1024  std::cerr << "MonitoringFile::copyHistograms(): "
1025  << "No input file is open\n";
1026  return false;
1027  }
1028 
1029  DirMap_t indirmap;
1030  DirMap_t reducedmap;
1031  DirMap_t outdirmap;
1032 
1033  if( dirName != "all" ) {
1034  TKey* dkey = getObjKey( m_file, dirName );
1035  if( dkey == 0 ) {
1036  std::cerr << "MonitoringFile::copyHistograms(): "
1037  << "Directory \'" << dirName << "\' not found in input file\n";
1038  return false;
1039  }
1040 
1041  TDirectory* fromDir = dynamic_cast<TDirectory*>(dkey->ReadObj());
1042 
1043  DirMap_t::value_type dirmapVal( dirName, fromDir );
1044  indirmap.insert( dirmapVal );
1045  }
1046  else {
1047  std::cout << "Building list of all TDirectories in file...\n" << std::flush;
1048  getAllDirs( indirmap, m_file, "" );
1049  }
1050 
1051  DirMap_t::const_iterator idirend = indirmap.end();
1052  for( DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir ) {
1053 
1054  std::string idirName = idir->first;
1055  std::cout << "Checking " << idirName << "\n" << std::flush;
1056  //std::string::size_type j = idirName.find( "L1Calo/1_PPr_EmFADCTiming" );
1057  //if( j != std::string::npos ) {
1058  // std::cerr << "Skipping directory \"" << idirName << "\"\n";
1059  // std::cerr << std::flush;
1060  // continue;
1061  //}
1062 
1063  if( !dirHasHistogramsInMetadata(idir->second) ) {
1064  continue;
1065  }
1066 
1067  reducedmap.insert( *idir );
1068  }
1069 
1070  std::unique_ptr<TFile> outfile( TFile::Open(outFileName.c_str(),"RECREATE",outFileName.c_str(),m_fileCompressionLevel) );
1071  if( outfile.get() == 0 ) {
1072  std::cerr << "MonitoringFile::copyHistograms(): "
1073  << "Output file not opened\n";
1074  return false;
1075  }
1076 
1077  idirend = reducedmap.end();
1078  for( DirMap_t::const_iterator idir = reducedmap.begin(); idir != idirend; ++idir ) {
1079 
1080  std::string idirName = idir->first;
1081  std::cout << "Processing " << idirName << "\n" << std::flush;
1082 
1083  TDirectory* toDir = createDir( outdirmap, outfile.get(), "", idirName );
1084  if( toDir == 0 ) {
1085  std::cerr << "MonitoringFile::copyHistograms(): "
1086  << "Directory \'" << idirName << "\' not created in output file\n";
1087  return false;
1088  }
1089 
1090  CopyHistogram copyFcn( toDir, idirName );
1091 
1092  loopOnHistogramsInMetadata( copyFcn, idir->second );
1093  }
1094 
1095  outfile->Write();
1096  outfile->Close();
1097 
1098  // gROOT->SetMustClean(useRecursiveDelete);
1099  return true;
1100 }
1101 
1102 
1103 
1104 std::string
1106 getHanResults( const std::string & hanResultsDir, const std::string & input,
1107  const std::string & hcfg, const std::string & hcfg_lowStat, const std::string & hcfg_medStat )
1108 {
1109  //DisableMustClean disabled;
1110 
1111  std::cout << "\nUsing han configurations:\n"
1112  << " entire run: " << hcfg << "\n"
1113  << " low stat interval: " << hcfg_lowStat << "\n"
1114  << " medium stat interval: " << hcfg_medStat << "\n\n" << std::flush;
1115 
1116 
1117  TFile* infile = TFile::Open( input.c_str() );
1118  if( infile == 0 ) {
1119  std::cerr << "MonitoringFile::getHanResults(): "
1120  << "Cannot open input file \"" << input << "\"\n";
1121  return "";
1122  }
1123 
1124  std::vector<std::string> run_dirs;
1125  std::vector<std::string> lowStat_dirs;
1126  std::vector<std::string> medStat_dirs;
1127 
1128  TIter next_run( infile->GetListOfKeys() );
1129  TKey* key_run(0);
1130  while( (key_run = dynamic_cast<TKey*>( next_run() )) != 0 ) {
1131  TObject* obj_run = key_run->ReadObj();
1132  TDirectory* tdir_run = dynamic_cast<TDirectory*>( obj_run );
1133  if( tdir_run != 0 ) {
1134  std::string tdir_run_name( tdir_run->GetName() );
1135  if( tdir_run_name.find("run") != std::string::npos ) {
1136  run_dirs.push_back( tdir_run_name );
1137  TIter next_minutes( tdir_run->GetListOfKeys() );
1138  TKey* key_minutes(0);
1139  while( (key_minutes = dynamic_cast<TKey*>( next_minutes() )) != 0 ) {
1140  TObject* obj_minutes = key_minutes->ReadObj();
1141  TDirectory* tdir_minutes = dynamic_cast<TDirectory*>( obj_minutes );
1142  if( tdir_minutes != 0 ) {
1143  std::string tdir_minutes_name( tdir_minutes->GetName() );
1144  if( tdir_minutes_name.find("lowStat") != std::string::npos ) {
1145  lowStat_dirs.push_back( tdir_run_name + '/' + tdir_minutes_name );
1146  }
1147  else if( tdir_minutes_name.find("medStat") != std::string::npos ) {
1148  medStat_dirs.push_back( tdir_run_name + '/' + tdir_minutes_name );
1149  }
1150  }
1151  delete obj_minutes;
1152  }
1153  }
1154  }
1155  delete obj_run;
1156  }
1157 
1158  delete infile;
1159 
1160  dqi::HanApp han;
1161 
1162  std::string fileList =" ";
1163  std::vector<std::string>::const_iterator dirs_end;
1164  std::vector<std::string>::const_iterator dir;
1165 
1166  dirs_end = run_dirs.end();
1167  for( dir = run_dirs.begin(); dir != dirs_end; ++dir ) {
1168  const std::string& tdir_run_name = *dir;
1169  std::string han_output_run = hanResultsDir+'/'+tdir_run_name+"_han.root";
1170  std::cout << "Calling han( " << hcfg << ", " << input << ", " << tdir_run_name
1171  << ", " << han_output_run << " ):\n" << std::flush;
1172  han.Analyze( hcfg, input, han_output_run, tdir_run_name );
1173  std::cout << "\n";
1174  fileList += han_output_run + " " + tdir_run_name + "\n" ;
1175  }
1176 
1177  dirs_end = lowStat_dirs.end();
1178  for( dir = lowStat_dirs.begin(); dir != dirs_end; ++dir ) {
1179  const std::string& tdir_minutes_path = *dir;
1180 
1181  std::string tdir_minutes_underscore = tdir_minutes_path;
1182  std::string::size_type tdir_minutes_i = tdir_minutes_underscore.find('/');
1183  tdir_minutes_underscore.replace( tdir_minutes_i, 1, "_" );
1184 
1185  std::string han_output_lowStat = hanResultsDir+'/'+tdir_minutes_underscore+"_han.root";
1186  std::cout << "Running han, writing to " << han_output_lowStat << ":\n" << std::flush;
1187  han.Analyze( hcfg_lowStat, input, han_output_lowStat, tdir_minutes_path );
1188  std::cout << "\n";
1189  std::string subdirname( tdir_minutes_path, tdir_minutes_i+1, std::string::npos );
1190  std::string dirname( tdir_minutes_path, 0, tdir_minutes_i );
1191  fileList += han_output_lowStat + " " + subdirname + " " + dirname + " " + subdirname +"\n" ;
1192  }
1193 
1194  dirs_end = medStat_dirs.end();
1195  for( dir = medStat_dirs.begin(); dir != dirs_end; ++dir ) {
1196  const std::string& tdir_minutes_path = *dir;
1197 
1198  std::string tdir_minutes_underscore = tdir_minutes_path;
1199  std::string::size_type tdir_minutes_i = tdir_minutes_underscore.find('/');
1200  tdir_minutes_underscore.replace( tdir_minutes_i, 1, "_" );
1201 
1202  std::string han_output_medStat = hanResultsDir+'/'+tdir_minutes_underscore+"_han.root";
1203  std::cout << "Running han, writing to " << han_output_medStat << ":\n" << std::flush;
1204  han.Analyze( hcfg_medStat, input, han_output_medStat, tdir_minutes_path );
1205  std::cout << "\n";
1206  std::string subdirname( tdir_minutes_path, tdir_minutes_i+1, std::string::npos );
1207  std::string dirname( tdir_minutes_path, 0, tdir_minutes_i );
1208  fileList += han_output_medStat + " " + subdirname + " " + dirname + " " + subdirname +"\n" ;
1209  }
1210 
1211  return fileList;
1212 }
1213 
1214 
1215 void
1218 {
1219  if( m_file == 0 ) {
1220  std::cerr << "MonitoringFile::printHanConfig(): "
1221  << "No input file is open\n";
1222  return;
1223  }
1224 
1225  DirMap_t indirmap;
1226 
1227  getAllDirs( indirmap, m_file, "" );
1228 
1229  std::string indent, indent_p,indent_c;
1230  std::string idirName_p;
1231  DirMap_t::const_iterator idirend = indirmap.end();
1232  for( DirMap_t::const_iterator idir = indirmap.begin(); idir != idirend; ++idir ) {
1233  std::string idirName = idir->first;
1234  std::string::size_type shortNameIndex = idirName.rfind( '/' );
1235  std::string shortName = idirName.substr( shortNameIndex+1, std::string::npos );
1236 
1237  std::string::size_type fsIndex = idirName.find( '/' );
1238  std::string shortPath;
1239  if( fsIndex != shortNameIndex )
1240  shortPath = idirName.substr( fsIndex+1, shortNameIndex );
1241  else
1242  shortPath = idirName.substr( fsIndex+1, std::string::npos );
1243 
1244  std::cout << idirName << "\n";
1245  std::cout << shortPath << ", " << shortName << "\n";
1246  /*
1247  indent = getIndentation(idirName,"");
1248  if(int(indent.size())==in_p){
1249  std::cout << indent << "} \n";
1250  std::cout << indent << "dir " << shortName << " { \n";
1251  std::cout << indent << " output " << idirName << "\n";
1252  std::cout << indent << " hist all_in_dir { \n " << indent << " } \n";
1253  }
1254  else if (int(indent.size()) > in_p){
1255  std::cout << indent << "dir " << shortName << " { \n";
1256  std::cout << indent << " output " << idirName << "\n";
1257  std::cout << indent << " hist all_in_dir { \n " << indent << " } \n";
1258  }
1259  else{
1260  //find common part + number of common '/'
1261  std::string common = FindCommon(idirName,idirName_p);
1262  indent_c = getIndentation(common,"");
1263  int counter = (indent_p.size() - indent_c.size())/2;
1264  for (int i = counter; i>0; i--){
1265  std::string temp = indent_c;
1266  for (int j = 0; j< i; j++){
1267  temp+=" ";
1268  }
1269  std::cout << temp << "} \n" ;
1270  }
1271  std::cout << indent << "} \n";
1272  std::cout << indent << "dir " << shortName << " { \n";
1273  std::cout << indent << " output " << idirName << "\n";
1274  std::cout << indent << " hist all_in_dir { \n " << indent << " } \n";
1275  }
1276  indent_p = indent;
1277  in_p = indent_p.size();
1278  idirName_p = idirName;
1279  */
1280  }
1281 }
1282 
1283 
1284 
1285 std::string
1287 getIndentation( const std::string & pathName, const std::string & leadingSpace )
1288 {
1289  std::string space = leadingSpace;
1290  std::string::size_type i = pathName.find_first_of('/');
1291  if( i != std::string::npos ) {
1292  std::string subPath( pathName, i+1, std::string::npos );
1293  space += " ";
1294  return getIndentation( subPath, space );
1295  }
1296  return space;
1297 }
1298 
1299 std::string
1301 FindCommon(const std::string & name1,const std::string & name2) const
1302 {
1303  int length = ( name1.size() < name2.size() ) ? name1.size() : name2.size();
1304  bool found = true;
1305  int count = 0;
1306  while (found==true && count < length){
1307  if (name1[count]==name2[count]){
1308  count++;
1309  }
1310  else {
1311  found = false;
1312  }
1313  }
1314  return (name1.substr(0,count));
1315 }
1316 
1317 
1318 
1319 // *********************************************************************
1320 // Protected Methods
1321 // *********************************************************************
1322 
1324 CopyHistogram( TDirectory* target, const std::string & dirName )
1325  : m_target(target)
1326  , m_dirName(dirName)
1327  , m_metadata(0)
1328 {
1329  m_metadata = new TTree( "metadata", "Monitoring Metadata" );
1330  m_metadata->SetDirectory(0);
1331  m_metadata->Branch( "Name", (void*) nullptr, "Name/C" );
1332  m_metadata->Branch( "Interval", (void*) nullptr, "Interval/C" );
1333  m_metadata->Branch( "TriggerChain", (void*) nullptr, "TriggerChain/C" );
1334  m_metadata->Branch( "MergeMethod", (void*) nullptr, "MergeMethod/C" );
1335 }
1336 
1337 
1340 {
1341  m_target->cd();
1342  m_metadata->SetDirectory(m_target);
1343  m_metadata->Write();
1344  delete m_metadata;
1345 }
1346 
1347 
1348 bool
1350 execute( TH1* hist )
1351 {
1352  m_target->cd();
1353  hist->SetDirectory(m_target);
1354  hist->Write();
1355 
1356  return true;
1357 }
1358 
1359 
1360 bool
1362 execute( TGraph* graph )
1363 {
1364  m_target->cd();
1365  graph->Write();
1366 
1367  return true;
1368 }
1369 
1370 bool MonitoringFile::CopyHistogram::execute( TEfficiency* eff ) {
1371  m_target->cd();
1372  eff->Write();
1373  return true;
1374 }
1375 
1376 void
1378 fillMD( const MetaData& md )
1379 {
1380  std::string name(md.name);
1381  std::string interval(md.interval);
1382  std::string chain(md.chain);
1383  std::string merge(md.merge);
1384  m_metadata->SetBranchAddress( "Name", name.data() );
1385  m_metadata->SetBranchAddress( "Interval", interval.data() );
1386  m_metadata->SetBranchAddress( "TriggerChain", chain.data() );
1387  m_metadata->SetBranchAddress( "MergeMethod", merge.data() );
1388  m_metadata->Fill();
1389 }
1390 
1391 bool
1393 executeMD( TH1* hist, const MetaData& md )
1394 {
1395  m_target->cd();
1396  hist->SetDirectory(m_target);
1397  hist->Write();
1398 
1399  fillMD( md );
1400 
1401  return true;
1402 }
1403 
1404 
1405 bool
1407 executeMD( TGraph* graph, const MetaData& md )
1408 {
1409  m_target->cd();
1410  graph->Write();
1411 
1412  fillMD( md );
1413 
1414  return true;
1415 }
1416 
1417 
1418 bool MonitoringFile::CopyHistogram::executeMD( TEfficiency* eff, const MetaData& md ) {
1419  m_target->cd();
1420  eff->Write();
1421  fillMD( md );
1422  return true;
1423 }
1424 
1425 
1427 GatherStatistics( const std::string & dirName )
1428  : m_dirName(dirName)
1429  , m_nHist1D(0)
1430  , m_nHist1DBins(0)
1431  , m_nGraph(0)
1432  , m_nGraphPoints(0)
1433  , m_nHist2D(0)
1434  , m_nHist2DBins(0)
1435 {
1436 }
1437 
1438 
1439 bool
1441 execute( TH1* hist )
1442 {
1443  TH2* hist2d = dynamic_cast<TH2*>( hist );
1444  if( hist2d != 0 ) {
1445  ++m_nHist2D;
1446  m_nHist2DBins += (hist2d->GetNbinsX() * hist2d->GetNbinsY());
1447  return true;
1448  }
1449  ++m_nHist1D;
1450  m_nHist1DBins += hist->GetNbinsX();
1451  return true;
1452 }
1453 
1454 
1455 bool
1457 execute( TGraph* graph )
1458 {
1459  ++m_nGraph;
1460  m_nGraphPoints += graph->GetMaxSize();
1461  return true;
1462 }
1463 
1464 
1465 bool MonitoringFile::GatherStatistics::execute( TEfficiency* eff ) {
1466  ++m_nEfficiency;
1467 
1468  TH1* h_total = eff->GetCopyPassedHisto();
1469  TH2* h_total2D = dynamic_cast<TH2*>( h_total );
1470 
1471  if( h_total2D != 0 ) {
1472  m_nEfficiencyBins += (h_total2D->GetNbinsX() * h_total2D->GetNbinsY());
1473  return true;
1474  } else {
1475  m_nEfficiencyBins += h_total->GetNbinsX();
1476  return true;
1477  }
1478 }
1479 
1480 
1482 GatherNames()
1483 {
1484 }
1485 
1486 
1487 bool
1489 execute( TH1* hist )
1490 {
1491  m_names.push_back( std::string(hist->GetName()) );
1492  return true;
1493 }
1494 
1495 
1496 bool
1498 execute( TGraph* graph )
1499 {
1500  m_names.push_back( std::string(graph->GetName()) );
1501  return true;
1502 }
1503 
1504 
1505 bool MonitoringFile::GatherNames::execute( TEfficiency* eff ) {
1506  m_names.push_back( std::string(eff->GetName()) );
1507  return true;
1508 }
1509 
1510 
1511 void
1513 clearData()
1514 {
1516 
1517  delete m_file;
1518  m_file = 0;
1519  m_debugLevel=0;
1521  m_doTiming=false;
1522  delete m_mergeMatchHistoRE;
1523  delete m_mergeMatchDirRE;
1528  m_useRE=false;
1529 }
1530 
1531 
1532 bool
1534 dirHasHistogramsInMetadata( TDirectory* dir )
1535 {
1536  dir->cd();
1537 
1538  TKey* mdKey = dir->FindKey( "metadata" );
1539  if( mdKey == 0 ) {
1540  return false;
1541  }
1542 
1543  TTree* md = dynamic_cast<TTree*>( mdKey->ReadObj() );
1544  if ( md == 0 ) {
1545  return false;
1546  }
1547 
1548  int counter = 0;
1549  int nEntries = int( md->GetEntries() );
1550 
1551  while( counter < nEntries ) {
1552  try {
1553  md->GetEntry(counter);
1554  }
1555  catch( const std::exception& e ) {
1556  std::cerr << "Exception: \"" << e.what() << "\" in directory \""
1557  << dir->GetName() << "\"\n" << std::flush;
1558  return false;
1559  }
1560 
1561  return true;
1562  ++counter;
1563  }
1564 
1565  return false;
1566 }
1567 
1568 
1569 void
1571 loopOnHistograms( HistogramOperation& fcn, TDirectory* dir )
1572 {
1573  TIter next( dir->GetListOfKeys() );
1574  TKey* key;
1575  while( (key = dynamic_cast<TKey*>( next() )) != 0 ) {
1576  TObject* obj = key->ReadObj();
1577  TH1* h(0);
1578  TGraph* g(0);
1579  TEfficiency* e(0);
1580  if ((h = dynamic_cast<TH1*>(obj))) {
1581  fcn.execute( h );
1582  } else if ((g = dynamic_cast<TGraph*>(obj))) {
1583  fcn.execute( g );
1584  } else if ((e = dynamic_cast<TEfficiency*>(obj))) {
1585  fcn.execute( e );
1586  }
1587  delete obj;
1588  }
1589 }
1590 
1591 
1592 bool
1594 loopOnHistogramsInMetadata( HistogramOperation& fcn, TDirectory* dir )
1595 {
1596  dir->cd();
1597  TKey* mdKey = dir->FindKey( "metadata" );
1598  if( mdKey == 0 ) {
1599  return false;
1600  }
1601 
1602  TTree* md = dynamic_cast<TTree*>( mdKey->ReadObj() );
1603  if ( md == 0 ) {
1604  return false;
1605  }
1606 
1607  TKey* i_key;
1608 
1609  TTreeReader reader(md);
1610  TTreeReaderArray<char> i_name(reader, "Name");
1611  TTreeReaderArray<char> i_interval(reader, "Interval");
1612  TTreeReaderArray<char> i_chain(reader, "TriggerChain");
1613  TTreeReaderArray<char> i_merge(reader, "MergeMethod");
1614 
1615  while (reader.Next()) {
1616  const std::string nameStr(static_cast<char*>(i_name.GetAddress()));
1617  dir->cd();
1618  i_key = dir->FindKey( static_cast<char*>(i_name.GetAddress()) );
1619  if( i_key == 0 ) {
1620  std::cerr << "MonitoringFile::loopOnHistogramsInMetadata(): "
1621  << "No \'" << nameStr << "\' object found\n";
1622  return false;
1623  }
1624  MetaData md( nameStr,
1625  static_cast<char*>(i_interval.GetAddress()),
1626  static_cast<char*>(i_chain.GetAddress()),
1627  static_cast<char*>(i_merge.GetAddress()) );
1628  TObject* obj = i_key->ReadObj();
1629  TH1* h = dynamic_cast<TH1*>( obj );
1630  if( h != 0 ) {
1631  fcn.executeMD( h, md );
1632  }
1633  else {
1634  TGraph* g = dynamic_cast<TGraph*>( obj );
1635  if( g != 0 ) {
1636  fcn.executeMD( g, md );
1637  }
1638  }
1639  delete obj;
1640  }
1641 
1642  delete md;
1643 
1644  return true;
1645 }
1646 
1647 
1648 bool
1650 setListFromFile( std::vector<std::string>& filelist, const std::string& listFileName )
1651 {
1652  using namespace std;
1653 
1654  filelist.clear();
1655 
1656  ifstream listfile( listFileName.c_str() );
1657  if(!listfile) {
1658  cerr << "MonitoringFile::setListFromFile(): "
1659  << "cannot read from file: " << listFileName << "\n";
1660  return false;
1661  }
1662 
1663  string line;
1664  char c;
1665  string filename;
1666  while( getline(listfile,line) ) {
1667  istringstream linestream(line);
1668  while(linestream.get(c)) {
1669  if(!isspace(c)) {
1670  // ignore comments
1671  if(c == '#') {
1672  break;
1673  }
1674 
1675  linestream.putback(c);
1676  linestream >> filename;
1677  if(!linestream) {
1678  cerr << "MonitoringFile::setListFromFile(): "
1679  << "badly formatted line: " << line << "\n";
1680  break;
1681  }
1682 
1683  filelist.push_back(filename);
1684  }
1685  }
1686  }
1687 
1688  return true;
1689 }
1690 
1691 int MonitoringFile::mergeObjs(TObject *objTarget, TObject *obj, const std::string & mergeType, debugLevel_t debugLevel, const std::string& objPath) {
1692  // merge obj into objTarget based on method specified in mergeType
1693  // copied in large parts from mergeDirectory
1694  std::string name("mergeObjs");
1695  if( ! objTarget ) {
1696  std::cerr << name << ": empty target object pointer" << std::endl;
1697  return -1;
1698  }
1699  if( ! obj ) {
1700  std::cerr << name << ": empty object pointer" << std::endl;
1701  return -1;
1702  }
1703 
1704  if( debugLevel >= VERBOSE )
1705  std::cout << name << ": obj->GetName() = " << obj->GetName() << ", mergeType = " << mergeType << ", class = " << obj->IsA()->GetName() << std::endl;
1706 
1707  const std::clock_t cpuStart=std::clock();
1708  TH1 *h=0, *nextH=0;
1709  TH2 *h2=0, *nextH2=0;
1710  TGraph *g=0;
1711  TTree *t=0;
1712  TEfficiency *e=0;
1713 
1714 // h = dynamic_cast<TH1*>( objTarget );
1715 // g = dynamic_cast<TGraph*>( objTarget );
1716 // t = dynamic_cast<TTree*>( objTarget );
1717  if((h = dynamic_cast<TH1*>( objTarget )) ) { // we are dealing with histograms
1718  /* if ( debugLevel >= DEBUG )
1719  std::cout << " --> " << name << " is a histogram */
1720  nextH = dynamic_cast<TH1*>( obj );
1721  if (!nextH) {
1722  std::cerr << objTarget->GetName() << " is a TH1, but " << obj->GetName() << " is not: skip merging" << std::endl;
1723  return -1;
1724  }
1725  if( mergeType == "effAsPerCent" ) {
1726  if((h2 = dynamic_cast<TH2*>( objTarget )) && (nextH2 = dynamic_cast<TH2*>( nextH ))){
1727  merge_effAsPerCent( *h2, *nextH2 );
1728  }else{
1729  merge_effAsPerCentAlt( *h, *nextH );
1730  }
1731  }else if( mergeType == "perBinEffPerCent" ) {
1732  merge_perBinEffPerCent( *h, *nextH );
1733  }else if( mergeType == "weightedAverage" ) {
1734  merge_weightedAverage( *h, *nextH );
1735  }else if( mergeType == "weightedAverage2D" ) {
1736  //if( h2 && nextH2 ) merge_weightedAverage( *h2, *nextH2 );
1737  merge_weightedAverage( *h, *nextH );
1738  }else if( mergeType == "weightedEff" ) {
1739  merge_weightedEff( *h, *nextH );
1740  }else if( mergeType == "mergeRebinned" ) {
1741  merge_Rebinned( *h, *nextH );
1742  }else if( mergeType == "eventSample" ) {
1743  if((h2 = dynamic_cast<TH2*>( objTarget ))&& (nextH2 = dynamic_cast<TH2*>( nextH ))){
1744  merge_eventSample( *h2, *nextH2 );
1745  }
1746  }else if( mergeType == "mergeRMS" ) {
1747  merge_RMS( *h, *nextH );
1748  }else if( mergeType == "RMSpercentDeviation" ) {
1749  merge_RMSpercentDeviation( *h, *nextH );
1750  }else if( mergeType == "lowerLB" ) {
1751  merge_lowerLB( *h, *nextH );
1752  }else if( mergeType == "identical" ) {
1753  merge_identical( *h, *nextH );
1754  }else if( mergeType == "merge" ) {
1755  TList tl; tl.Add(nextH); h->Merge(&tl);
1756  } else {
1757  if (!h->Add( nextH )) {
1758  std::cerr << "Histogram " << h->GetName() << " should NOT be using Add: needs to specify a merge method (e.g. merge) in its metadata\n";
1759  }
1760  }
1761  }else if( (g = dynamic_cast<TGraph*>( objTarget )) ) { // TGraphs
1762  if( mergeType != "<default>" ) {
1763  std::cerr << name << ": TGraph " << obj->GetName() << " request mergeType = " << mergeType
1764  << " but only default merging implemented for TGraphs\n";
1765  }
1766  TGraph *nextG = dynamic_cast<TGraph*>( obj );
1767  TList listG;
1768  listG.Add( nextG );
1769  g->Merge( &listG );
1770  listG.Clear();
1771  }else if( (e = dynamic_cast<TEfficiency*>( objTarget )) ) { // TEfficiencies
1772  if( mergeType != "<default>" ) {
1773  std::cerr << name << ": TEfficiency " << obj->GetName() << " request mergeType = " << mergeType
1774  << " but only default merging implemented for TEfficiencies.\n";
1775  }
1776  TEfficiency *nextE = dynamic_cast<TEfficiency*>( obj );
1777  TList listE;
1778  listE.Add( nextE );
1779  e->Merge( &listE );
1780  listE.Clear();
1781  }else if ((t = dynamic_cast<TTree*>( objTarget ))) { // TTrees
1782  if ( debugLevel >= VERBOSE) {
1783  std::cout << "Merging Tree " << obj->GetName() << std::endl;
1784  }
1785  if( mergeType != "<default>" ) {
1786  std::cerr << name << ": TTree " << obj->GetName() << " request mergeType = " << mergeType
1787  << " but only default merging implemented for TTrees\n";
1788  }
1789  TTree *nextT = dynamic_cast<TTree*>( obj );
1790  TList listT;
1791  listT.Add( nextT );
1792  t->Merge( &listT );
1793  listT.Clear();
1794  } else {
1795  std::cerr << name << ": object is not a histogram or graph, merging not implemented" << std::endl;
1796  }
1797  if (m_doTiming) {
1798  const std::clock_t duration=std::clock()-cpuStart;
1799  std::string name;
1800  if (!objPath.empty()) {
1801  size_t pSlash=0;
1802  //Ignore the first two /xx/yy/zz/ sub-strings (filename, run_NNNNNN)
1803  for (unsigned i=0;i<3 && pSlash!=std::string::npos;++i) {
1804  pSlash=objPath.find_first_of('/',pSlash+1);
1805  }
1806  if (pSlash != std::string::npos) {
1807  name=objPath.substr(pSlash+1);
1808  }
1809  else {
1810  name=objPath;
1811  }
1812  name+="/";
1813  }
1814  name+=obj->GetName();
1816  }
1817  return 0;
1818 }
1819 
1820 int MonitoringFile::mergeLB_recursiveDirCopy(TDirectory *dir_top_out, TDirectory *dir_out, TDirectory *cwd,
1821  std::vector<std::string>& v_dirsSub, debugLevel_t& debugLevel) {
1822  // store in v_dirsSub the paths (relative to dir_top_out) of all subdirectories of cwd
1823  // copy the subfolder structure from cwd to dir_out
1824  std::string name("mergeLB_recursiveDirCopy");
1825  if( ! cwd ) {
1826  std::cerr << name << ": empty directory pointer cwd" << std::endl;
1827  return -1;
1828  }
1829  if( ! dir_top_out ) {
1830  std::cerr << name << ": empty directory pointer dir_top_out" << std::endl;
1831  return -1;
1832  }
1833  if( ! dir_out ) {
1834  std::cerr << name << ": empty directory pointer dir_out" << std::endl;
1835  return -1;
1836  }
1837 
1838  TIter next(cwd->GetListOfKeys());
1839  TKey *key;
1840  while( ( key=(TKey*) next() ) ) {
1841  std::string keyClassName(key->GetClassName());
1842  if( (keyClassName.size() > 9) && (keyClassName.substr(0,10) == "TDirectory") ) {
1843  TDirectory *dir = (TDirectory*) cwd->Get(key->GetName());
1844  if( !dir ) {
1845  std::cerr << name << ": could not retrieve directory " << key->GetName() <<
1846  " from " << cwd->GetPath() << std::endl;
1847  continue;
1848  }
1849  dir_out->cd();
1850  std::string p_top(dir_top_out->GetPath());
1851  std::string p(gDirectory->GetPath());
1852  if( p_top.size() < p.size() ) {
1853  p = p.substr(p_top.size()+1, p.size()-p_top.size()-1); // strip off the top directory part
1854  p = p + '/';
1855  }
1856  else p = "";
1857 
1858  // is this directory already in the list of subdirectories?
1860  for( it = v_dirsSub.begin(); it != v_dirsSub.end(); ++it ) {
1861  if( *it == (p + dir->GetName()) ) break;
1862  }
1863  if( it == v_dirsSub.end() ) {
1864  // no
1865  v_dirsSub.push_back(p + dir->GetName());
1866  }
1867 
1868  TKey *test_key = dir_out->FindKey(dir->GetName());
1869  TDirectory *dir_out_new(0);
1870  if( !test_key ) {
1871  if( debugLevel >= DEBUG ) {
1872  std::cout << name << ": creating subdirectory " << dir->GetName();
1873  if( p.size() != 0 ) std::cout << " in " << p << std::endl;
1874  else std::cout << std::endl;
1875  }
1876  dir_out_new = (TDirectory*) gDirectory->mkdir(dir->GetName());
1877  if( ! dir_out_new ) {
1878  std::cerr << name << ": could not create directory " << dir->GetName()
1879  << " in " << gDirectory->GetPath() << std::endl;
1880  }
1881  }
1882  else {
1883  if( debugLevel >= DEBUG )
1884  std::cout << name << ": " << dir_out->GetPath() << '/' << dir->GetName() << " exists already" << std::endl;
1885 
1886  dir_out_new = (TDirectory*) dir_out->Get(test_key->GetName());
1887  if( ! dir_out_new ) {
1888  std::cerr << name << ": could not retrieve directory " << test_key->GetName()
1889  << " from " << dir_out->GetPath() << std::endl;
1890  }
1891  }
1892  // go one level deeper in the directory tree
1893  if( dir_out_new )
1894  mergeLB_recursiveDirCopy(dir_top_out, dir_out_new, dir, v_dirsSub, debugLevel);
1895 
1896  }
1897  }
1898  return 0;
1899 }
1900 
1901 int MonitoringFile::mergeLB_createListOfHistos(TDirectory *dir_top, TDirectory *cwd, std::vector<std::string>& v_histos, debugLevel_t& debugLevel) {
1902  // get paths relative to dir_top of all histograms and graphs in cwd
1903  std::string name("mergeLB_createListOfHistos");
1904  if( ! cwd ) {
1905  std::cerr << name << ": empty directory pointer" << std::endl;
1906  return -1;
1907  }
1908 
1909  TIter next(cwd->GetListOfKeys());
1910  TKey *key;
1911  while( ( key=(TKey*) next() ) ) {
1912  std::string keyClassName(key->GetClassName());
1913  if( ( (keyClassName.size() > 2) && ( (keyClassName.substr(0,3) == "TH1") || (keyClassName.substr(0,3) == "TH2") ) ) ||
1914  ( (keyClassName.size() > 7) && ( (keyClassName.substr(0,8) == "TProfile") ) ) ||
1915  ( (keyClassName.size() > 5) && ( (keyClassName.substr(0,6) == "TGraph") ) ) ||
1916  ( (keyClassName.size() > 10) && ( (keyClassName.substr(0,11) == "TEfficiency") ) ) ) {
1917  if( debugLevel >= VERBOSE )
1918  std::cout << name << ": found object: " << key->GetName();
1919 
1920  // add to v_histos if not already in it
1921  std::string p_top(dir_top->GetPath());
1922  std::string p(cwd->GetPath());
1923  if( p_top.size() < p.size() ) {
1924  p = p.substr(p_top.size()+1, p.size()-p_top.size()-1); // strip off the top directory part
1925  p = p + '/';
1926  }
1927  else p = "";
1928 
1930  for( it = v_histos.begin(); it != v_histos.end(); ++it ) {
1931  if( *it == (p + key->GetName()) ) break;
1932  }
1933 
1934  if( it == v_histos.end() ) {
1935  std::string objName(p + key->GetName());
1936  v_histos.push_back(objName);
1937  if( debugLevel >= VERBOSE )
1938  std::cout << ", added to list: " << p + key->GetName() << std::endl;
1939  }
1940  else {
1941  if( debugLevel >= VERBOSE )
1942  std::cout << ", already in list" << std::endl;
1943  }
1944  }
1945  }
1946  return 0;
1947 }
1948 
1949 int MonitoringFile::mergeLB_processLBinterval(std::vector<TDirectory*>& v_dirsStat, TDirectory *dir_run, debugLevel_t& debugLevel) {
1950  // create a directory for merged histograms in dir_run
1951  // loop over v_dirsStat directories (=different LB intervals)
1952  // and merge all histograms and graphs (preserving the subdirectory structure)
1953  std::string name("mergeLB_processLBinterval");
1954 
1955  if( v_dirsStat.size() == 0 ) return 0;
1956 
1957  if( ! dir_run ) {
1958  std::cerr << name << ": empty pointer dir_run" << std::endl;
1959  return -1;
1960  }
1961 
1962  if( ! v_dirsStat[0] ) {
1963  std::cerr << name << ": empty first directory pointer" << std::endl;
1964  return -1;
1965  }
1966 
1967 /*
1968  // create top-level merged directory
1969  std::string label((v_dirsStat[0])->GetName());
1970  label = label.substr(0,3);
1971  std::string dirMergedName("merged_" + label + "Stat");
1972  TDirectory *dir_merged = dir_run->mkdir(dirMergedName.c_str());
1973  if( !dir_merged ) {
1974  std::cerr << name << ": could not create directory " << dirMergedName << std::endl;
1975  return -1;
1976  }
1977  if( debugLevel >= DEBUG )
1978  std::cout << name << ": created new directory " << dir_merged->GetPath() << std::endl;
1979 */
1980  TDirectory *dir_merged = dir_run;
1981 
1982  // Histograms can be booked on demand in AthenaMonitoring.
1983  // So a histogram might be present in lowStat_LB21-30 but not
1984  // in lowStat_LB1-10. Also entire directories might be missing
1985  // in certain LB intervals.
1986  // Hence, to cope with on-demand-booking have to loop over all
1987  // LB intervals to identify all histograms.
1988 
1989  // To limit memory usage, instead of holding all merged histograms in
1990  // memory, build a list of histogram names (including full path because
1991  // can have same name in different subfolders, like Jets/Topo/JetP and
1992  // Jets/Tower/JetP).
1993 
1994  // Build this list only per subfolder. Then loop over list, merge the
1995  // histograms, write them to ROOT file, and delete them from memory.
1996 
1997  // instead of a list, create a map which also holds the merging type
1998  // (whether simply TH1F::Add() or more complicated function) from metadata.
1999 
2000  std::vector<TDirectory*>::const_iterator i;
2001  // loop over LB intervals:
2002  // - get list of subdirectories
2003  // - and create subdirectory structure in merged directory
2004  std::vector<std::string> v_dirsSub;
2005  for( i = v_dirsStat.begin(); i != v_dirsStat.end(); ++i ) {
2006  TDirectory *dirStat = *i;
2007  if( debugLevel >= DEBUG )
2008  if( dirStat )
2009  std::cout << name << ": getting input from directory " << dirStat->GetPath() << std::endl;
2010  mergeLB_recursiveDirCopy(dir_merged, dir_merged, dirStat, v_dirsSub, debugLevel);
2011  // v_dirsSub are paths relative to dir_merged
2012  }
2013 
2014  // loop over subdirectories:
2015  if( v_dirsSub.size() == 0 ) {
2016  if( debugLevel >= DEBUG )
2017  std::cout << name << ": no subdirectories found" << std::endl;
2018  return 0;
2019  }
2020  // - create list of histograms
2021  // - loop over all LB intervals because of on-demand-booking
2022  // - loop over histogram list
2023  // - loop over LB intervals
2024  // - merge histograms
2025  // - write merged histogram to file and delete it from memory
2026  std::vector<std::string>::const_iterator it_string;
2027  for( it_string = v_dirsSub.begin(); it_string != v_dirsSub.end(); ++it_string ) {
2028  std::string dirFullName = *it_string;
2029  std::vector<std::string> v_histos;
2030  if( debugLevel >= DEBUG )
2031  std::cout << name << ": processing " << dirFullName << std::endl;
2032  for( i = v_dirsStat.begin(); i != v_dirsStat.end(); ++i ) {
2033  TDirectory *dirStat = *i;
2034  TDirectory *dir = (TDirectory*) dirStat->Get(dirFullName.c_str());
2035  if( !dir ) {
2036  std::cerr << name << ": could not retrieve directory " << dirFullName <<
2037  " from " << dirStat->GetPath() << std::endl;
2038  continue;
2039  }
2040  if( debugLevel >= DEBUG )
2041  std::cout << name << ": processing LB folder " << dir->GetPath() << std::endl;
2042  mergeLB_createListOfHistos(dirStat, dir, v_histos, debugLevel);
2043  }
2044 
2045  if( v_histos.size() == 0 ) {
2046  if( debugLevel >= DEBUG )
2047  std::cout << name << ": no objects found" << std::endl;
2048  continue;
2049  }
2050 
2051  TDirectory *dir_out = (TDirectory*) dir_merged->Get(dirFullName.c_str());
2052  if( !dir_out ) {
2053  std::cerr << name << ": could not retrieve directory " << dirFullName <<
2054  " from " << dir_merged->GetPath() << std::endl;
2055  continue;
2056  }
2057 
2058  // create new metadata tree for current merged directory if not already extant
2059  typedef std::map< std::string, MetaData > MetaDataMap_t;
2060  TTree* mdTree = dynamic_cast<TTree*>(dir_out->Get("metadata"));
2061  if (!mdTree) {
2062  mdTree = new TTree( "metadata", "Monitoring Metadata" );
2063  }
2064  mdTree->SetDirectory(0);
2065  OutputMetadata outputmd( mdTree );
2066 
2067  // get metadata from one of the input directories
2068  // this is for caching, could also read the metadata directly from tree in the
2069  // current directory when accessing the histogram
2070  MetaDataMap_t mdMap;
2071  TDirectory *dir_in = (TDirectory*) v_dirsStat[0]->Get(dirFullName.c_str());
2072  if( !dir_in ) {
2073  std::cerr << name << ": could not retrieve directory " << dirFullName <<
2074  " from " << v_dirsStat[0]->GetPath() << std::endl;
2075  continue;
2076  }
2077  fillMetaDataMap( mdMap, dir_in);
2078 
2079  // histogram loop
2080  std::vector<std::string>::const_iterator it_string2;
2081  for( it_string2 = v_histos.begin(); it_string2 != v_histos.end(); ++it_string2 ) {
2082  std::string histFullName = *it_string2; // something like Jets/Tower/JetP
2083 
2084  TObject *objMerged(0);
2085  std::string mergeType("<default>");
2086  // LB interval loop
2087  bool key_checked = false;
2088  for( i = v_dirsStat.begin(); i != v_dirsStat.end(); ++i ) {
2089  // retrieve histogram for current LB interval
2090  TDirectory *dir_current = (*i);
2091  std::unique_ptr<TObject> objThis((TObject*) dir_current->Get(histFullName.c_str()));
2092 
2093  if( ! objThis.get() ) { // histogram does not exist in this LB interval
2094  continue;
2095  }
2096 
2097  // test if histogram exists already in dir_out
2098  if (! key_checked) {
2099  TKey *test_key = dir_out->FindKey(objThis->GetName());
2100  if( test_key ) {
2101  if( debugLevel >= DEBUG )
2102  std::cout << name << ": " << dir_out->GetPath() << '/' << objThis->GetName()
2103  << " exists already, not written" << std::endl;
2104  break;
2105  }
2106  key_checked = true;
2107  }
2108 
2109  if( ! objMerged ) {
2110  // clone the current histogram
2111  objMerged = objThis->Clone();
2112  // retrieve metadata
2113  MetaDataMap_t::iterator mdi = mdMap.find(objThis->GetName());
2114  const MetaData *md(0);
2115  if( mdi != mdMap.end() ) {
2116  md = &(mdi->second);
2117  }
2118  else {
2119  // it could be that we had just been unlucky (on-demand-booking)
2120  // and this histogram was not available in v_dirsStat[0]
2121  // (or the directory for which we created the map last here).
2122  // remake metadatamap
2123  mdMap.clear();
2124  fillMetaDataMap( mdMap, dir_current );
2125  mdi = mdMap.find(objThis->GetName());
2126  if( mdi != mdMap.end() ) {
2127  md = &(mdi->second);
2128  }
2129  }
2130 
2131  if( ! md ) {
2132  std::cerr << name << ": no metadata for " << histFullName << std::endl;
2133  std::cerr << name << ": => using default merging" << std::endl;
2134  }
2135  else {
2136  outputmd.fill( md->name, md->interval, md->chain, md->merge );
2137  mergeType = md->merge;
2138  }
2139  }
2140  else {
2141  // objMerged already exists, merge with objThis
2142  // but only if objMerged isn't empty ... otherwise swap
2143  TH1* h = dynamic_cast<TH1*>(objMerged);
2144  if (h && h->GetEntries() == 0 && h->GetSumOfWeights() == 0) {
2145  delete objMerged;
2146  objMerged = objThis->Clone();
2147  } else {
2148  mergeObjs(objMerged, objThis.get(), mergeType, debugLevel, std::string(dir_out->GetPath()));
2149  }
2150  }
2151  //delete objThis;
2152  }
2153 
2154  dir_out->cd();
2155  // write histogram to file and delete it from memory
2156  if( objMerged ) {
2157  objMerged->Write();
2158  if( debugLevel >= DEBUG )
2159  std::cout << name << ": wrote " << dir_out->GetPath() << '/' << objMerged->GetName() << std::endl;
2160  delete objMerged;
2161  }
2162  }
2163  // write metadata tree
2164  dir_out->cd();
2165  mdTree->SetDirectory(dir_out);
2166  mdTree->Write(0, kOverwrite);
2167  delete mdTree;
2168 
2169  }
2170 
2171  return 0;
2172 }
2173 
2174 void MonitoringFile::buildLBToIntervalMap(std::vector<TDirectory*>& v_dirLBs, std::vector<TDirectory*>& v_dirsInterval, map_dir_vdir& mapping, debugLevel_t& debugLevel) {
2175  std::vector<std::string> v_splits;
2176  typedef std::vector<std::pair<TDirectory*, std::pair<int, int> > > range_t;
2177  range_t v_ranges;
2178  for (std::vector<TDirectory*>::const_iterator dirit = v_dirsInterval.begin();
2179  dirit != v_dirsInterval.end();
2180  ++dirit) {
2181  std::string dirname((*dirit)->GetName());
2182  std::string corename(dirname.substr(10, std::string::npos));
2183  boost::split(v_splits, corename, boost::algorithm::is_any_of(std::string("-")));
2184  if (v_splits.size() != 2) {
2185  std::cerr << "Unable to properly parse " << (*dirit)->GetName() << std::endl;
2186  continue;
2187  }
2188  if( debugLevel >= DEBUG ) std::cout << "Found " << dirname << " "
2189  << v_splits[0] << " "
2190  << v_splits[1] << std::endl;
2191  try {
2192  v_ranges.push_back(std::make_pair(*dirit, std::make_pair(boost::lexical_cast<int>(v_splits[0]), boost::lexical_cast<int>(v_splits[1]))));
2193  } catch (boost::bad_lexical_cast& e) {
2194  std::cerr << "Unable to cast to integers: " << v_splits[0] << " "
2195  << v_splits[1] << std::endl;
2196  }
2197  }
2198  for (std::vector<TDirectory*>::const_iterator dirit = v_dirLBs.begin();
2199  dirit != v_dirLBs.end();
2200  ++dirit) {
2201  std::string dirname((*dirit)->GetName());
2202  int lbnum = boost::lexical_cast<int>(dirname.substr(3, std::string::npos));
2203  for (range_t::const_iterator rangeit = v_ranges.begin();
2204  rangeit != v_ranges.end(); ++rangeit) {
2205  if ((*rangeit).second.first <= lbnum &&
2206  lbnum <= (*rangeit).second.second) {
2207  map_dir_vdir::iterator mapit = mapping.find((*rangeit).first);
2208  (*mapit).second.push_back(*dirit);
2209  }
2210  }
2211  }
2212 }
2213 
2214 int MonitoringFile::mergeLB_processLB(std::vector<TDirectory*>& v_dirLBs, std::vector<TDirectory*>& v_dirsInterval, debugLevel_t& debugLevel) {
2215  std::map<TDirectory*,std::vector<TDirectory*> > mapping;
2216  for (std::vector<TDirectory*>::const_iterator dirit = v_dirsInterval.begin();
2217  dirit != v_dirsInterval.end(); ++dirit) {
2218  mapping[*dirit] = std::vector<TDirectory*>();
2219  }
2220  buildLBToIntervalMap(v_dirLBs, v_dirsInterval, mapping, debugLevel);
2221 
2222  for (map_dir_vdir::iterator mapit = mapping.begin();
2223  mapit != mapping.end(); ++mapit) {
2224  mergeLB_processLBinterval((*mapit).second, (*mapit).first, debugLevel);
2225  }
2226 
2227  return 0;
2228 }
2229 
2230 int MonitoringFile::mergeLB_processRun(TDirectory *dir_run, debugLevel_t& debugLevel) {
2231  // get lists of "lowStat_", "medStat_", "higStat_" subdirectories in dir_run
2232  // call mergeLB_processLBinterval for each of these lists
2233  std::string name("mergeLB_processRun");
2234  if( ! dir_run ) {
2235  std::cerr << name << ": empty pointer to run directory" << std::endl;
2236  return -1;
2237  }
2238 
2239  if( debugLevel >= DEBUG )
2240  std::cout << name << ": processing dir " << dir_run->GetName() << std::endl;
2241 
2242  std::vector<TDirectory*> v_dirsLowStat, v_dirsMedStat, v_dirsHigStat,
2243  v_dirsLB;
2244 
2245  TIter next(dir_run->GetListOfKeys());
2246  TKey *key;
2247  while( ( key=(TKey*) next() ) ) {
2248  std::string keyClassName(key->GetClassName());
2249  if( (keyClassName.size() > 9) && (keyClassName.substr(0,10) == "TDirectory") ) {
2250  TDirectory *dir = (TDirectory*) dir_run->Get(key->GetName());
2251  if( !dir ) {
2252  std::cerr << name << ": could not retrieve " << key->GetName() << " from " << dir_run->GetPath() << std::endl;
2253  continue;
2254  }
2255  std::string dirName(dir->GetName());
2256  if ( dirName.substr(0,3) == "lb_" ) {
2257  v_dirsLB.push_back(dir);
2258  } else if( dirName.size() > 7 ) {
2259  if( dirName.substr(0,8) == "lowStat_" ) {
2260  v_dirsLowStat.push_back(dir);
2261  }
2262  else if( dirName.substr(0,8) == "medStat_" ) {
2263  v_dirsMedStat.push_back(dir);
2264  }
2265  else if( dirName.substr(0,8) == "higStat_" ) {
2266  v_dirsHigStat.push_back(dir);
2267  }
2268  }
2269  }
2270  }
2271 
2272  if( debugLevel >= DEBUG ) std::cout << "\n" << name << ": processing LB directories" << std::endl;
2273  if( v_dirsLB.size() > 0 ) mergeLB_processLB(v_dirsLB, v_dirsLowStat, debugLevel);
2274 
2275  if( debugLevel >= DEBUG ) std::cout << "\n" << name << ": processing lowStat directories" << std::endl;
2276  if( v_dirsLowStat.size() > 0 ) mergeLB_processLBinterval(v_dirsLowStat, dir_run, debugLevel);
2277 
2278  if( debugLevel >= DEBUG ) std::cout << "\n" << name << ": processing medStat directories" << std::endl;
2279  if( v_dirsMedStat.size() > 0 ) mergeLB_processLBinterval(v_dirsMedStat, dir_run, debugLevel);
2280 
2281  if( debugLevel >= DEBUG ) std::cout << "\n" << name << ": processing higStat directories" << std::endl;
2282  if( v_dirsHigStat.size() > 0 ) mergeLB_processLBinterval(v_dirsHigStat, dir_run, debugLevel);
2283 
2284  return 0;
2285 }
2286 
2287 int MonitoringFile::mergeLBintervals(const std::string& inFilename, const std::string& inDebugLevel) {
2288  // open merged file, call mergeLB_processRun for each "run_" directory
2289  // in file, close file
2290  std::string name("mergeLBintervals");
2291 
2293  if(inDebugLevel.empty()){
2295  }else{
2296  if( inDebugLevel == "DEBUG" ) debugLevel = DEBUG;
2297  else if( inDebugLevel == "VERBOSE" ) debugLevel = VERBOSE;
2298  }
2299 
2300  //TFile &f = *(TFile::Open(inFilename.c_str(), "UPDATE")); // does a copy and leaks memory
2301  TFile *f = (TFile::Open(inFilename.c_str(), "UPDATE",inFilename.c_str(),m_fileCompressionLevel));
2302 
2303  TIter next(f->GetListOfKeys());
2304  TKey *key;
2305  while( ( key=(TKey*) next() ) ) {
2306  std::string keyClassName(key->GetClassName());
2307  if( (keyClassName.size() > 9) && (keyClassName.substr(0,10) == "TDirectory") ) {
2308  TDirectory *dir = (TDirectory*) f->Get(key->GetName());
2309  if( !dir ) {
2310  std::cerr << name << ": could not retrieve " << key->GetName()
2311  << " from top level directory of " << inFilename << std::endl;
2312  continue;
2313  }
2314  std::string dirName(dir->GetName());
2315  if( (dirName.size() > 3) && (dirName.substr(0,4) == "run_") ) {
2316  if( debugLevel == DEBUG )
2317  std::cout << name << ": found run dir " << dirName << std::endl;
2318  // process this run
2320  }
2321  }
2322  }
2323 
2324  f->Close();
2325  return 0;
2326 }
2327 
2328 bool
2330 CheckHistogram(TFile* f,const char* HistoName)
2331 {
2332  std::unique_ptr<TObject> obj(f->Get(HistoName));
2333  if (! obj.get()) {
2334  //std::cerr<<"No such histogram \""<< HistoName << "\"\n";
2335  return false;
2336  }
2337  else return true;
2338 }
2339 
2342 void MonitoringFile::doTiming() {m_doTiming=true;}
2343 std::atomic<int> MonitoringFile::m_fileCompressionLevel=1;
2344 std::atomic<int> MonitoringFile::m_debugLevel=0;
2345 bool MonitoringFile::m_doTiming=false;
2346 std::unordered_map<std::string,std::clock_t> MonitoringFile::m_cpuPerHistogram;
2347 
2348 std::string MonitoringFile::getPath(TDirectory *dir){
2349 
2350  std::string path = dir->GetPath();
2351  if ( path.find(':') != std::string::npos )
2352  path = path.substr(path.rfind(':')+1);
2353 
2354  return path;
2355 }
2356 
2357 } // namespace dqutils
2358 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
dqutils::MonitoringFile::merge_effAsPerCentAlt
static void merge_effAsPerCentAlt(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:212
dqutils::MonitoringFile::getAllDirs
static void getAllDirs(DirMap_t &dirmap, TDirectory *dir, const std::string &dirName)
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
HanApp.h
dqutils::MonitoringFile::copyHistograms
virtual bool copyHistograms(const std::string &outFileName, const std::string &dirName="all")
Copy the indicated set of histograms to an output file.
dqutils::MonitoringFile::VERBOSE
@ VERBOSE
Definition: MonitoringFile.h:425
checkFileSG.line
line
Definition: checkFileSG.py:75
ReadCellNoiseFromCool.name1
name1
Definition: ReadCellNoiseFromCool.py:233
athena.path
path
python interpreter configuration --------------------------------------—
Definition: athena.py:128
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
dqutils::MonitoringFile::createDir
static TDirectory * createDir(DirMap_t &dirmap, TDirectory *dir, const std::string &parent, const std::string &path)
dqutils::MonitoringFile
Definition: MonitoringFile.h:54
run.infile
string infile
Definition: run.py:13
dqutils::MonitoringFile::setDebugLevel
static void setDebugLevel(int level)
vtune_athena.format
format
Definition: vtune_athena.py:14
FullCPAlgorithmsTest_eljob.flush
flush
Definition: FullCPAlgorithmsTest_eljob.py:182
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
dqutils::MonitoringFile::GatherNames::GatherNames
GatherNames()
dqutils::MonitoringFile::CheckHistogram
static bool CheckHistogram(TFile *f, const char *HistoName)
rootconvert.fName
string fName
Definition: rootconvert.py:5
dqutils::MonitoringFile::printHanConfig
virtual void printHanConfig()
dqutils::MonitoringFile::CopyHistogram::execute
virtual bool execute(TH1 *hist)
hist_file_dump.d
d
Definition: hist_file_dump.py:137
plotmaker.hist
hist
Definition: plotmaker.py:148
Epos_Base_Fragment.inputFiles
string inputFiles
Definition: Epos_Base_Fragment.py:18
dqutils::MonitoringFile::merge_effAsPerCent
static void merge_effAsPerCent(TH2 &a, const TH2 &b)
Definition: MonitoringFile_MergeAlgs.cxx:64
dqutils::MonitoringFile::m_mergeMatchDirREString
std::string m_mergeMatchDirREString
Definition: MonitoringFile.h:447
skel.it
it
Definition: skel.GENtoEVGEN.py:396
dqutils::MonitoringFile::merge_lowerLB
static void merge_lowerLB(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:647
dirname
std::string dirname(std::string name)
Definition: utils.cxx:200
dqutils::MonitoringFile::CopyHistogram::executeMD
virtual bool executeMD(TH1 *hist, const MetaData &md)
dqutils::MonitoringFile::CopyHistogram::CopyHistogram
CopyHistogram(TDirectory *target, const std::string &dirName)
dqutils::MonitoringFile::merge_Rebinned
static void merge_Rebinned(TH1 &a, TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:478
dqutils::MonitoringFile::getDebugLevel
static int getDebugLevel()
CscCalibQuery.fileList
fileList
Definition: CscCalibQuery.py:330
dqutils::MonitoringFile::clearData
virtual void clearData()
TrigInDetValidation_Base.test
test
Definition: TrigInDetValidation_Base.py:147
dqutils::MonitoringFile::DirMap_t
std::map< std::string, TDirectory * > DirMap_t
Definition: MonitoringFile.h:88
dqutils::MonitoringFile::mergeLB_processLBinterval
static int mergeLB_processLBinterval(std::vector< TDirectory * > &, TDirectory *, debugLevel_t &)
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
python.base_data.hcfg
hcfg
Definition: base_data.py:22
dqutils::MonitoringFile::getObjKey
static TKey * getObjKey(TDirectory *dir, const std::string &path)
dqi::DisableMustClean
Definition: HanUtils.h:30
dqutils::MonitoringFile::CopyHistogram::fillMD
void fillMD(const MetaData &md)
find_tgc_unfilled_channelids.mapping
mapping
Definition: find_tgc_unfilled_channelids.py:17
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
dqutils::MonitoringFile::MonitoringFile
MonitoringFile()
dqutils::keycyclemap
std::map< std::string, std::vector< int > > keycyclemap
Definition: MonitoringFile.h:51
python.iconfTool.models.loaders.level
level
Definition: loaders.py:20
dqutils::MonitoringFile::getHanResults
static std::string getHanResults(const std::string &hanResultsDir, const std::string &input, const std::string &hcfg, const std::string &hcfg_min10, const std::string &hcfg_min30)
dqutils::MonitoringFile::~MonitoringFile
virtual ~MonitoringFile()
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
LArCellBinning_test.retval
def retval
Definition: LArCellBinning_test.py:112
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
dqutils::MonitoringFile::m_debugLevel
static std::atomic< int > m_debugLevel
Definition: MonitoringFile.h:449
DumpGeoConfig.outFileName
string outFileName
Definition: DumpGeoConfig.py:252
dqutils::MonitoringFile::fillMetaDataMap
static void fillMetaDataMap(std::map< std::string, dqutils::MonitoringFile::MetaData > &mdMap, TDirectory *dir)
dqutils::MonitoringFile::loopOnHistograms
static void loopOnHistograms(HistogramOperation &fcn, TDirectory *dir)
dqutils::MonitoringFile::m_cpuPerHistogram
static std::unordered_map< std::string, std::clock_t > m_cpuPerHistogram
Definition: MonitoringFile.h:452
dqutils::MonitoringFile::loopOnHistogramsInMetadata
static bool loopOnHistogramsInMetadata(HistogramOperation &fcn, TDirectory *dir)
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
Get
T * Get(TFile &f, const std::string &n, const std::string &dir="", const chainmap_t *chainmap=0, std::vector< std::string > *saved=0)
get a histogram given a path, and an optional initial directory if histogram is not found,...
Definition: comparitor.cxx:179
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
covarianceTool.pathName
pathName
Definition: covarianceTool.py:704
dqutils::MonitoringFile::OutputMetadata::makeBranch
void makeBranch(const char *branchName, const char *branchstr)
dqutils::MonitoringFile::CopyHistogram::~CopyHistogram
virtual ~CopyHistogram()
geometry_dat_to_json.indent
indent
Definition: geometry_dat_to_json.py:36
dqutils::populateKeyMapping
void populateKeyMapping(TDirectory *, keycyclemap &)
fillPileUpNoiseLumi.next
next
Definition: fillPileUpNoiseLumi.py:52
CaloCondBlobAlgs_fillNoiseFromASCII.inputFile
string inputFile
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:17
ParseInputs.gDirectory
gDirectory
Definition: Final2012/ParseInputs.py:133
dqutils::MonitoringFile::OutputMetadata::fill
virtual void fill(const std::string &name, const std::string &interval, const std::string &chain, const std::string &merge)
lumiFormat.i
int i
Definition: lumiFormat.py:85
dqutils::MonitoringFile::m_file
TFile * m_file
Definition: MonitoringFile.h:419
h
python.CaloCondTools.g
g
Definition: CaloCondTools.py:15
dqutils::MonitoringFile::map_dir_vdir
std::map< TDirectory *, std::vector< TDirectory * > > map_dir_vdir
Definition: MonitoringFile.h:427
HanUtils.h
extractSporadic.h
list h
Definition: extractSporadic.py:97
dqutils::MonitoringFile::setHistogramRegEx
bool setHistogramRegEx(const std::string &re)
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
dqutils::MonitoringFile::m_mergeMatchHistoREString
std::string m_mergeMatchHistoREString
Definition: MonitoringFile.h:446
getLatestRuns.interval
interval
Definition: getLatestRuns.py:24
generateReferenceFile.files
files
Definition: generateReferenceFile.py:12
calibdata.exception
exception
Definition: calibdata.py:496
dqutils::getOutputDirectory
std::string getOutputDirectory(const std::string &inputDirName, TFile *input, bool has_multiple_runs, std::map< TFile *, std::string > *prefixes)
test_pyathena.parent
parent
Definition: test_pyathena.py:15
dqutils::MonitoringFile::getPath
static std::string getPath(TDirectory *dir)
dqutils::MonitoringFile::mergeLB_processRun
static int mergeLB_processRun(TDirectory *, debugLevel_t &)
hist_file_dump.f
f
Definition: hist_file_dump.py:135
TestSUSYToolsAlg.inputDir
string inputDir
Definition: TestSUSYToolsAlg.py:74
SCT_Monitoring::disabled
@ disabled
Definition: SCT_MonitoringNumbers.h:60
dqutils::getInputDirectory
std::string getInputDirectory(const std::string &outputDirName, TFile *input, bool has_multiple_runs, std::map< TFile *, std::string > *prefixes)
DQHistogramMerge.debugLevel
debugLevel
Definition: DQHistogramMerge.py:41
index.currentDir
currentDir
Definition: index.py:37
plotmaker.keyName
keyName
Definition: plotmaker.py:145
xAOD::double
double
Definition: CompositeParticle_v1.cxx:159
dqutils
Definition: CoolMdt.h:76
skel.allFiles
list allFiles
Definition: skel.GENtoEVGEN.py:742
CscCalibQuery.outputDir
string outputDir
Definition: CscCalibQuery.py:261
dqutils::MonitoringFile::mergeLB_recursiveDirCopy
static int mergeLB_recursiveDirCopy(TDirectory *, TDirectory *, TDirectory *, std::vector< std::string > &, debugLevel_t &)
PixelAthHitMonAlgCfg.duration
duration
Definition: PixelAthHitMonAlgCfg.py:152
dqutils::MonitoringFile::none
@ none
Definition: MonitoringFile.h:425
beamspotman.dir
string dir
Definition: beamspotman.py:623
dqutils::MonitoringFile::debugLevel_t
debugLevel_t
Definition: MonitoringFile.h:424
dqt_zlumi_alleff_HIST.lbnum
lbnum
Definition: dqt_zlumi_alleff_HIST.py:106
dqutils::MonitoringFile::doTiming
void doTiming()
dqutils::MonitoringFile::merge_RMS
static void merge_RMS(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:534
dqutils::MonitoringFile::merge_weightedAverage
static void merge_weightedAverage(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:290
dqutils::MonitoringFile::buildLBToIntervalMap
static void buildLBToIntervalMap(std::vector< TDirectory * > &, std::vector< TDirectory * > &, map_dir_vdir &, debugLevel_t &)
dqutils::MonitoringFile::mergeObjs
static int mergeObjs(TObject *, TObject *, const std::string &, debugLevel_t debugLevel=none, const std::string &path="")
dqutils::MonitoringFile::GatherStatistics::GatherStatistics
GatherStatistics(const std::string &dirName)
han
Definition: han.py:1
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
dqutils::MonitoringFile::mergeLB_processLB
static int mergeLB_processLB(std::vector< TDirectory * > &, std::vector< TDirectory * > &, debugLevel_t &)
runegammaMonitoring.isDir
isDir
Definition: runegammaMonitoring.py:37
dqi::HanApp
Definition: HanApp.h:21
dqutils::MonitoringFile::mergeObjsMultiCycles
static void mergeObjsMultiCycles(const std::string &, const std::vector< int > &, TDirectory *, const std::string &, std::unique_ptr< TObject > &)
dqutils::MonitoringFile::dirHasHistogramsInMetadata
static bool dirHasHistogramsInMetadata(TDirectory *dir)
dqutils::MonitoringFile::m_mergeMatchHistoRE
std::regex * m_mergeMatchHistoRE
Definition: MonitoringFile.h:444
dqutils::MonitoringFile::printDirectories
virtual void printDirectories()
dqutils::MonitoringFile::GatherNames::execute
virtual bool execute(TH1 *hist)
dqutils::MonitoringFile::OutputMetadata::OutputMetadata
OutputMetadata(TTree *metadata)
cwd
std::string cwd
Definition: listroot.cxx:38
ALFA_EventTPCnv_Dict::t2
std::vector< ALFA_RawDataContainer_p1 > t2
Definition: ALFA_EventTPCnvDict.h:44
dqutils::MonitoringFile::setDirectoryRegEx
bool setDirectoryRegEx(const std::string &re)
MonitoringFile.h
dqutils::MonitoringFile::DEBUG
@ DEBUG
Definition: MonitoringFile.h:425
dqutils::MonitoringFile::mergeLBintervals
static int mergeLBintervals(const std::string &, const std::string &debugLevel="none")
dqutils::MonitoringFile::m_doTiming
static bool m_doTiming
Definition: MonitoringFile.h:451
a
TList * a
Definition: liststreamerinfos.cxx:10
h
CondAlgsOpts.found
int found
Definition: CondAlgsOpts.py:101
dqutils::MonitoringFile::mergeDirectory
void mergeDirectory(TDirectory *outputDir, const std::vector< TFile * > &inputFiles, bool has_multiple_runs=false, std::map< TFile *, std::string > *prefixes=0)
dqutils::MonitoringFile::m_fileCompressionLevel
static std::atomic< int > m_fileCompressionLevel
Definition: MonitoringFile.h:450
copySelective.target
string target
Definition: copySelective.py:37
dqutils::MonitoringFile::merge_identical
static void merge_identical(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:694
python.envutil.filelist
filelist
print ("Checking files %s..." % fullfile)
Definition: envutil.py:133
re
const boost::regex re(r_e)
python.utility.LHE.merge
def merge(input_file_pattern, output_file)
Merge many input LHE files into a single output file.
Definition: LHE.py:29
dqutils::MonitoringFile::mergeFiles
void mergeFiles(const std::string &outFileName, const std::vector< std::string > &files)
dqutils::MonitoringFile::OutputMetadata::m_metadata
TTree * m_metadata
Definition: MonitoringFile.h:78
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
CaloCellTimeCorrFiller.filename
filename
Definition: CaloCellTimeCorrFiller.py:24
python.base_data.hanResultsDir
hanResultsDir
Definition: base_data.py:32
dqutils::MonitoringFile::FindCommon
virtual std::string FindCommon(const std::string &name1, const std::string &name2) const
checkFileSG.fi
fi
Definition: checkFileSG.py:65
dqutils::MonitoringFile::GatherStatistics::execute
virtual bool execute(TH1 *hist)
ClassImp
ClassImp(dqutils::MonitoringFile) namespace dqutils
Definition: MonitoringFile.cxx:41
dqutils::MonitoringFile::getIndentation
static std::string getIndentation(const std::string &pathName, const std::string &leadingSpace="")
DiTauMassTools::MMCFitMethod::shortName
const std::string shortName[MAX]
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:48
dqt_zlumi_alleff_HIST.eff
int eff
Definition: dqt_zlumi_alleff_HIST.py:113
copySelective.source
string source
Definition: copySelective.py:32
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:798
dqutils::MonitoringFile::printStatistics
virtual void printStatistics()
dqt_zlumi_alleff_HIST.tl
tl
Definition: dqt_zlumi_alleff_HIST.py:73
dqutils::MonitoringFile::merge_perBinEffPerCent
static void merge_perBinEffPerCent(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:126
dqutils::MonitoringFile::mergeLB_createListOfHistos
static int mergeLB_createListOfHistos(TDirectory *, TDirectory *, std::vector< std::string > &, debugLevel_t &)
dqutils::MonitoringFile::m_useRE
bool m_useRE
Definition: MonitoringFile.h:448
collisions.reader
reader
read the goodrunslist xml file(s)
Definition: collisions.py:22
python.LumiCalcRecover.subdir
subdir
Definition: LumiCalcRecover.py:25
test_pyathena.counter
counter
Definition: test_pyathena.py:15
dqBeamSpot.nEntries
int nEntries
Definition: dqBeamSpot.py:73
python.PyAthena.obj
obj
Definition: PyAthena.py:132
dqutils::MonitoringFile::merge_weightedEff
static void merge_weightedEff(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:401
PrepareReferenceFile.outfile
outfile
Definition: PrepareReferenceFile.py:42
python.compressB64.c
def c
Definition: compressB64.py:93
length
double length(const pvec &v)
Definition: FPGATrackSimLLPDoubletHoughTransformTool.cxx:26
hist_file_dump.ordering
ordering
Definition: hist_file_dump.py:80
dqutils::MonitoringFile::setFile
virtual bool setFile(const std::string &fileName)
Clears all previous data and opens the file with the given name for analysis, returning a boolean ind...
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
dqutils::MonitoringFile::merge_RMSpercentDeviation
static void merge_RMSpercentDeviation(TH1 &a, const TH1 &b)
Definition: MonitoringFile_MergeAlgs.cxx:589
merge
Definition: merge.py:1
dqutils::MonitoringFile::setListFromFile
static bool setListFromFile(std::vector< std::string > &filelist, const std::string &listFileName)
dqutils::MonitoringFile::merge_eventSample
static void merge_eventSample(TH2 &a, const TH2 &b)
Definition: MonitoringFile_MergeAlgs.cxx:497
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
dqutils::MonitoringFile::m_mergeMatchDirRE
std::regex * m_mergeMatchDirRE
Definition: MonitoringFile.h:445