StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MergeHistogramFile.C
1 /*
2 
3  * $Id: MergeHistogramFile.C,v 3.17 2009/06/18 22:01:21 fine Exp $
4  Author: Valeri Fine fine@bnl.gov
5  Date: 25.06.2006
6 
7 
8  */
9 
10 
11 
12 #ifdef __CINT__
13 // # include "TDirIter.cxx"
14 #else
15 # include "TDirIter.h"
16 # include "StFileIter.h"
17 # include "TFileIter.h"
18 # include "TFile.h"
19 # include "TTree.h"
20 # include "TH1.h"
21 # include "TStopwatch.h"
22 #endif
23 
24 //________________________________________________________________________________
25 void MergeSimpleHistogramFile( const Char_t *TargetName=0, const Char_t *inputFilesPattern=0)
26 {
27  // This is the deprecated version. To be dleted after debugging
28  if (TargetName && TargetName[0] && inputFilesPattern && inputFilesPattern[0] ) {
29  TStopwatch time;
30  Int_t fileCounter = 0;
31  Int_t histogramCounter = 0;
32  // Create the output file
33  TFile *outFile = TFile::Open(TargetName,"RECREATE");
34  TDirIter listOfFiles(inputFilesPattern);
35  const char *fileName = 0;
36  while ( (fileName = listOfFiles.NextFile() ) ) {
37  printf(".");
38  fileCounter++;
39  TFileIter file(fileName);
40  TObject *obj = 0;
41  while ( (obj = *file) ) {
42  if ( obj->IsA()->InheritsFrom( "TH1" ) ) {
43  // descendant of TH1 -> merge it
44  // printf("Merging histogram: %s\n",obj->GetName() );
45 // std::cout << "Merging histogram " << obj->GetName() << std::endl;
46  TH1 *h1 = (TH1*)obj;
47  TH1 *dstHistogram = 0;
48  // Check whether we found the new histogram
49  if ( (dstHistogram = (TH1 *)outFile->FindObject(h1->GetName()))) {
50  // Accumulate the histogram
51  dstHistogram->Add(h1);
52  delete h1; // Optional, to reduce the memory consumption
53  printf("+");
54  } else {
55  // First time - move the histogram
56  h1->SetDirectory(outFile);
57  printf(" The new Histogram found: %s \n", h1->GetName() );
58  histogramCounter++;
59  }
60  } else {
61  // printf("Skipping object: %s\n",obj->GetName() );
62  }
63  ++file;
64  }
65 
66  }
67  printf("\n Finishing . . . \n");
68  outFile->ls();
69  outFile->Write();
70  outFile->Close();
71  delete outFile;
72  printf(" Total files merged: %d \n", fileCounter);
73  printf(" Total histograms merged: %d \n", histogramCounter);
74  time.Print("Merge");
75  } else {
76  printf("\nUsage: root MergeHistogramFile.C(\"DestinationFileName\",\"InputFilesPattern\",kTRUE)\n");
77  printf("------ where InputFilesPattern ::= <regexp_pattern_for_the_input_files>|@indirect_file_list\n");
78  printf(" indirect_file_list ::= a text file with the list of the files\n");
79  printf(" indirect_file_list can be create by the shell command:\n");
80  printf(" ls -1 --color=never *.root>indirect_file_list \n\n");
81  }
82 }
83 
84 //________________________________________________________________________________
85 void MergeComplexHistogramFile( const Char_t *TargetName=0, const Char_t *inputFilesPattern=0)
86 {
87  if (TargetName && TargetName[0] && inputFilesPattern && inputFilesPattern[0] ) {
88  printf(" An experimental version of macro.\n");
89  TStopwatch time;
90  Int_t fileCounter = 0;
91  Int_t dirCounter = 0;
92  Int_t treeCounter = 0;
93  Int_t histogramCounter = 0;
94  // Create the output file
95  TFile *outFile = TFile::Open(TargetName,"RECREATE");
96  TDirectory *outDir = outFile;
97  TDirIter listOfFiles(inputFilesPattern);
98  const char *fileName = 0;
99  while ( (fileName = listOfFiles.NextFile() ) ) {
100  Int_t currentDirDepth = 0;
101  printf(".");
102  fileCounter++;
103  StFileIter file(fileName);
104  TObject *obj = 0;
105  while ( (obj = *file) ) {
106  Int_t depth = file.GetDepth();
107  while (depth < currentDirDepth) {
108  outDir = outDir->GetMotherDir();
109  currentDirDepth--;
110  }
111  if ( obj->IsA()->InheritsFrom(TH1::Class()) ) {
112  // descendant of TH1 -> merge it
113  // printf("Merging histogram: %s\n",obj->GetName() );
114 // std::cout << "Merging histogram " << obj->GetName() << std::endl;
115  TH1 *h1 = (TH1*)obj;
116  TH1 *dstHistogram = 0;
117  // Check whether we found the new histogram
118  if ( (dstHistogram = (TH1 *)outDir->FindObject(h1->GetName()))) {
119  // Accumulate the histogram
120  dstHistogram->Add(h1);
121  delete h1; // Optional, to reduce the memory consumption
122  printf("h");
123  } else {
124  // First time - move the histogram
125  h1->SetDirectory(outDir);
126  printf(" The new Histogram found: %s \n", h1->GetName() );
127  histogramCounter++;
128  }
129  } else if ( obj->IsA()->InheritsFrom(TTree::Class()) ) {
130  // descendant of TTree -> merge it
131  // printf("Merging Tree %p:%s\n",obj, obj->GetName() );
132  TTree *tree = (TTree*)obj;
133  TTree *dstTree = 0;
134  // Check whether we found the new histogram
135  if ( (dstTree = (TTree *)outDir->FindObject(tree->GetName()))) {
136  // printf("Merging %p:%s with the existing Tree %p:%s\n"
137  // ,tree,tree->GetName(),dstTree, dstTree->GetName() );
138  // Merge the tree
139  TList *nextTree = new TList(); nextTree->Add(tree);
140  dstTree->Merge(nextTree);
141  delete tree; // Optional, to reduce the memory consumption
142  delete nextTree;
143  printf("t");
144  } else {
145  // First time - move the TTree
146  TDirectory *saveDir = 0;
147  if (outDir != gDirectory) {
148  saveDir = gDirectory;
149  outDir->cd();
150  }
151  TList *nextTree = new TList(); nextTree->Add(tree);
152  dstTree = TTree::MergeTrees(nextTree);
153  if (saveDir) saveDir->cd();
154  // printf(" The new TTree found: %p:%s \n",tree, tree->GetName() );
155  // printf(" Create the destination Tree %p:%s\n\n",dstTree, dstTree->GetName() );
156  delete tree; // Optional, to reduce the memory consumption
157  delete nextTree;
158  treeCounter++;
159  }
160  } else if ( obj->IsA()->InheritsFrom(TDirectory::Class()) ) {
161  printf("The input sub-TDirectory object: %s depth=%d\n",obj->GetName(), depth);
162  TDirectory *d = (TDirectory *)outDir->FindObject(obj->GetName());
163  if (!d) {
164  d = outDir->mkdir(obj->GetName());
165  dirCounter++;
166  printf("The new TDirectory object: %s depth=%d\n",d->GetPathStatic(), depth);
167  }
168  if (d) {
169  outDir = d;
170  printf("The output sub-TDirectory object: %s depth=%d\n",outDir->GetPathStatic(), depth);
171 
172  }
173  } else {
174  printf("I have no idea how to merge the %s objects of the %s class. Skipping .... \n",obj->GetName(), obj->ClassName() );
175  }
176  ++file;
177  }
178 
179  }
180  printf("\n Finishing . . . \n");
181  outFile->Write(); // this creates a second copy of the TTree ???
182  outFile->Close();
183  delete outFile;
184  if (fileCounter) printf(" Total files merged: %d \n", fileCounter);
185  if (dirCounter) printf(" Total TDirectory objects merged: %d \n", dirCounter);
186  if (histogramCounter) printf(" Total histograms merged: %d \n", histogramCounter);
187  if (treeCounter) printf(" Total TTree\'s merged: %d \n",treeCounter);
188  if (dirCounter || treeCounter) printf(" You have used the experimental version of the program. Please check the output file\n");
189 
190  time.Print("Merge");
191  } else {
192  printf("\nUsage: root MergeHistogramFile.C(\"DestinationFileName\",\"InputFilesPattern\")\n");
193  printf("------ where InputFilesPattern ::= <regexp_pattern_for_the_input_files>|@indirect_file_list\n");
194  printf(" indirect_file_list ::= a text file with the list of the files\n");
195  printf(" indirect_file_list can be create by the shell command:\n");
196  printf(" ls -1 *.root>indirect_file_list \n\n");
197  }
198 }
199 
200 
201 
202 //________________________________________________________________________________
203 void MergeHistogramFile( const Char_t *TargetName=0, const Char_t *inputFilesPattern=0, Bool_t simple=kFALSE)
204 {
205  if (TargetName && TargetName[0] && inputFilesPattern && inputFilesPattern[0] ) {
206  // by default hadd can merge Trees in a file that can go up to 100 Gbytes
207  Long64_t maxsize = 100000000; //100GB
208  maxsize *= 100; //to bypass some compiler limitations with big constants
209  TTree::SetMaxTreeSize(maxsize);
210  if (simple) {
211  // Use the deprecated version
212  MergeSimpleHistogramFile(TargetName, inputFilesPattern);
213  } else {
214 #ifdef __CINT__
215  gSystem->Load("St_base");
216 #endif
217  MergeComplexHistogramFile(TargetName, inputFilesPattern);
218  }
219  } else {
220  printf("\nUsage: root MergeHistogramFile.C(\"DestinationFileName\",\"InputFilesPattern\",kTRUE)\n");
221  printf("------ where InputFilesPattern ::= <regexp_pattern_for_the_input_files>|@indirect_file_list\n");
222  printf(" indirect_file_list ::= a text file with the list of the files\n");
223  printf(" indirect_file_list can be create by the shell command:\n\n");
224  printf(" ls -1 --color=never *.root>indirect_file_list \n\n");
225  printf(" The last parameter defines whether one wants to merge the \"simple\" ROOT files\n");
226  printf(" The \"simple\" ROOT files are those with no sub-TDirectrory objects inside and with no TTree/TNtuples\n");
227  printf(" This is the default option and it can be omitted\n");
228  printf(" To merge the ROOT files with sub-TDirectory or / and TTree pass the kFALSE as the third macro parameter\n\n");
229  printf("------------- To use with ACliC - load the \"St_base.so\" shared library first\n");
230 
231  }
232 }