CbmRoot
CbmHaddBase.cxx
Go to the documentation of this file.
1 
2 
3 #include <glob.h>
4 #include <sstream>
5 #include <string.h>
6 
7 
8 #include "CbmHaddBase.h"
9 #include "Riostream.h"
10 #include "TChain.h"
11 #include "TFile.h"
12 #include "TH1.h"
13 #include "TKey.h"
14 #include "TTree.h"
15 
16 using namespace std;
17 
18 
20 
21 
22 vector<string> CbmHaddBase::GetFilesByPattern(const string& pattern) {
23  glob_t glob_result;
24  glob(pattern.c_str(), GLOB_TILDE, NULL, &glob_result);
25  vector<string> files;
26  for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) {
27  files.push_back(string(glob_result.gl_pathv[i]));
28  }
29  globfree(&glob_result);
30  return files;
31 }
32 
33 
34 vector<string> CbmHaddBase::GetGoodFiles(const string& pattern,
35  Int_t fileSizeLimit,
36  Int_t nofEvents) {
37  vector<string> files = GetFilesByPattern(pattern);
38  cout << "pattern:" << pattern << endl;
39  cout << "# of files by pattern:" << files.size() << endl;
40  vector<string> goodFiles;
41  for (size_t i = 0; i < files.size(); i++) {
42  TFile* file = TFile::Open((files[i]).c_str(), "READ");
43  if (file != NULL) cout << i << " open file" << endl;
44  // TODO: Do we need to check also reco file?
45  Bool_t isGoodFile = CheckFile(file, fileSizeLimit, nofEvents);
46  if (file != NULL) file->Close();
47  if (isGoodFile) goodFiles.push_back(files[i]);
48  }
49  cout << "GetGoodFiles all:" << files.size() << " good:" << goodFiles.size()
50  << endl;
51  return goodFiles;
52 }
53 
54 Bool_t CbmHaddBase::CheckFileSize(TFile* file, Int_t fileSizeLimit) {
55  if (file == NULL) return false;
56  if (file->GetEND() < fileSizeLimit) return false;
57 
58  return true;
59 }
60 
61 
62 Bool_t
63 CbmHaddBase::CheckFile(TFile* file, Int_t fileSizeLimit, Int_t nofEvents) {
64  if (file == NULL) return false;
65  if (file->GetEND() < fileSizeLimit) return false;
66  TTree* tree = (TTree*) file->Get("cbmsim");
67  if (tree == NULL) return false;
68  Long64_t treeSizeAna = tree->GetEntriesFast();
69  if (treeSizeAna == nofEvents) return true;
70  return false;
71 }
72 
73 
74 void CbmHaddBase::AddFilesInDir(const string& dir,
75  const string& fileTemplate,
76  const string& addString,
77  Int_t nofFiles,
78  Int_t fileSizeLimit,
79  Int_t nofEvents) {
80  Int_t maxNofFiles = 100;
81  string fileNameAna = dir + string("analysis") + fileTemplate;
82  string fileNameReco = dir + string("reco") + fileTemplate;
83  string fileNameQa = dir + string("litqa") + fileTemplate;
84 
85  cout << "-I- " << dir << endl;
86  int count = 0;
87  TList* fileList = new TList();
88  TList* tempTargetFiles = new TList();
89  Int_t targetFileNum = 0;
90  for (int i = 1; i < nofFiles; i++) {
91  stringstream ss;
92  ss.fill('0');
93  ss.width(5);
94  ss << i << ".root";
95 
96  TFile* fileAna = TFile::Open((fileNameAna + ss.str()).c_str(), "READ");
97  TFile* fileReco = TFile::Open((fileNameReco + ss.str()).c_str(), "READ");
98 
99  Bool_t isGoodFile = CheckFile(fileAna, fileSizeLimit, nofEvents)
100  && CheckFile(fileReco, fileSizeLimit, nofEvents);
101  if (fileReco != NULL) fileReco->Close();
102  if (isGoodFile) {
103  if (addString == "analysis") {
104  fileList->Add(fileAna);
105  count++;
106  }
107  if (addString == "litqa") {
108  TFile* fileQa = TFile::Open((fileNameQa + ss.str()).c_str(), "READ");
109  Bool_t isGoodQaFile = CheckFileSize(fileQa, fileSizeLimit);
110  if (isGoodQaFile) {
111  fileList->Add(fileQa);
112  count++;
113  } else {
114  if (fileQa != NULL) fileQa->Close();
115  }
116  if (fileAna != NULL) fileAna->Close();
117  }
118  } else {
119  if (fileAna != NULL) fileAna->Close();
120  if (fileReco != NULL) fileReco->Close();
121  }
122 
123  if (fileList->GetEntries() >= maxNofFiles || i == nofFiles - 1) {
124  TFile* tf =
125  CreateAndMergeTempTargetFile(dir, addString, targetFileNum, fileList);
126  tempTargetFiles->Add(tf);
127  CloseFilesFromList(fileList);
128  fileList->RemoveAll();
129  targetFileNum++;
130  }
131  }
132  cout << endl << "-I- number of files to merge = " << count << endl << endl;
133 
134  string outputFile = fileNameAna + "all.root";
135  if (addString == "litqa") outputFile = fileNameQa + "all.root";
136  cout << "-I- OUTPUT: " << outputFile << endl;
137  TFile* targetFile = TFile::Open(outputFile.c_str(), "RECREATE");
138  MergeRootfile(targetFile, tempTargetFiles);
139  CloseFilesFromList(tempTargetFiles);
140  targetFile->Close();
141 
142  if (targetFile != NULL) delete targetFile;
143  if (tempTargetFiles != NULL) delete tempTargetFiles;
144  if (fileList != NULL) delete fileList;
145 }
146 
148  const string& addString,
149  Int_t targetFileNum,
150  TList* fileList) {
151  cout << "-I- CreateAndMergeTempTargetFile no:" << targetFileNum
152  << ", nofFiles:" << fileList->GetEntries() << endl;
153  stringstream ss;
154  ss << targetFileNum << ".root";
155  TFile* targetFile = TFile::Open(
156  string(dir + addString + ".temp.taget.file." + ss.str()).c_str(),
157  "RECREATE");
158  if (fileList->GetEntries() > 0) MergeRootfile(targetFile, fileList);
159  return targetFile;
160 }
161 
162 
163 void CbmHaddBase::CloseFilesFromList(TList* fileList) {
164  int nFL = fileList->GetEntries();
165  for (int iFL = 0; iFL < nFL; iFL++) {
166  TFile* f = (TFile*) fileList->At(iFL);
167  if (f != NULL) {
168  f->Close();
169  delete f;
170  }
171  }
172 }
173 
174 
175 void CbmHaddBase::MergeRootfile(TDirectory* target, TList* sourcelist) {
176  // cout << "Target path: " << target->GetPath() << endl;
177  TString path((char*) strstr(target->GetPath(), ":"));
178  path.Remove(0, 2);
179 
180  TFile* first_source = (TFile*) sourcelist->First();
181  first_source->cd(path);
182  TDirectory* current_sourcedir = gDirectory;
183  //gain time, do not add the objects in the list in memory
184  Bool_t status = TH1::AddDirectoryStatus();
185  TH1::AddDirectory(kFALSE);
186 
187  // loop over all keys in this directory
188  // TChain *globChain = 0;
189  TIter nextkey(current_sourcedir->GetListOfKeys());
190  TKey *key, *oldkey = 0;
191  while ((key = (TKey*) nextkey())) {
192  //keep only the highest cycle number for each key
193  if (oldkey && !strcmp(oldkey->GetName(), key->GetName())) continue;
194 
195  // read object from first source file
196  first_source->cd(path);
197  TObject* obj = key->ReadObj();
198 
199  if (obj->IsA()->InheritsFrom(TH1::Class())) {
200  // descendant of TH1 -> merge it
201 
202  // cout << "Merging histogram " << obj->GetName() << endl;
203  TH1* h1 = (TH1*) obj;
204 
205  // loop over all source files and add the content of the
206  // correspondant histogram to the one pointed to by "h1"
207  TFile* nextsource = (TFile*) sourcelist->After(first_source);
208  while (nextsource) {
209  // make sure we are at the correct directory level by cd'ing to path
210  nextsource->cd(path);
211  TKey* key2 =
212  (TKey*) gDirectory->GetListOfKeys()->FindObject(h1->GetName());
213  if (key2) {
214  TH1* h2 = (TH1*) key2->ReadObj();
215  h1->Add(h2);
216  delete h2;
217  }
218  // cout << nextsource->GetPath() << endl;
219  nextsource = (TFile*) sourcelist->After(nextsource);
220  }
221  }
222  // else if ( obj->IsA()->InheritsFrom( TTree::Class() ) ) {
223  //
224  // // loop over all source files create a chain of Trees "globChain"
225  // const char* obj_name= obj->GetName();
226  //
227  // globChain = new TChain(obj_name);
228  // globChain->Add(first_source->GetName());
229  // TFile *nextsource = (TFile*)sourcelist->After( first_source );
230  // // const char* file_name = nextsource->GetName();
231  // // cout << "file name " << file_name << endl;
232  // while ( nextsource ) {
233  //
234  // globChain->Add(nextsource->GetName());
235  // nextsource = (TFile*)sourcelist->After( nextsource );
236  // }
237  //
238  // } else if ( obj->IsA()->InheritsFrom( TDirectory::Class() ) ) {
239  // // it's a subdirectory
240  //
241  // cout << "Found subdirectory " << obj->GetName() << endl;
242  //
243  // // create a new subdir of same name and title in the target file
244  // target->cd();
245  // TDirectory *newdir = target->mkdir( obj->GetName(), obj->GetTitle() );
246  //
247  // // newdir is now the starting point of another round of merging
248  // // newdir still knows its depth within the target file via
249  // // GetPath(), so we can still figure out where we are in the recursion
250  // MergeRootfile( newdir, sourcelist );
251  //
252  // } else {
253  //
254  // // object is of no type that we know or can handle
255  // cout << "Unknown object type, name: "
256  // << obj->GetName() << " title: " << obj->GetTitle() << endl;
257  // }
258 
259  // now write the merged histogram (which is "in" obj) to the target file
260  // note that this will just store obj in the current directory level,
261  // which is not persistent until the complete directory itself is stored
262  // by "target->Write()" below
263  if (obj) {
264  target->cd();
265 
267  // if(obj->IsA()->InheritsFrom( TTree::Class() ))
268  // globChain->Merge(target->GetFile(),0,"keep");
269  // else
270  obj->Write(key->GetName());
271  }
272 
273  } // while ( ( TKey *key = (TKey*)nextkey() ) )
274 
275  // save modifications to target file
276  target->SaveSelf(kTRUE);
277  TH1::AddDirectory(status);
278 }
f
float f
Definition: L1/vectors/P4_F32vec4.h:24
CbmHaddBase::CreateAndMergeTempTargetFile
static TFile * CreateAndMergeTempTargetFile(const std::string &dir, const std::string &addString, Int_t targetFileNum, TList *fileList)
Definition: CbmHaddBase.cxx:147
i
int i
Definition: L1/vectors/P4_F32vec4.h:25
CbmHaddBase::CheckFile
static Bool_t CheckFile(TFile *file, Int_t fileSizeLimit=50000, Int_t nofEvents=1000)
Definition: CbmHaddBase.cxx:63
CbmHaddBase::CheckFileSize
static Bool_t CheckFileSize(TFile *file, Int_t fileSizeLimit=50000)
Definition: CbmHaddBase.cxx:54
CbmHaddBase::GetFilesByPattern
static vector< string > GetFilesByPattern(const string &pattern)
Definition: CbmHaddBase.cxx:22
CbmHaddBase.h
ClassImp
ClassImp(CbmHaddBase)
CbmHaddBase::MergeRootfile
static void MergeRootfile(TDirectory *target, TList *sourcelist)
Definition: CbmHaddBase.cxx:175
CbmHaddBase::AddFilesInDir
static void AddFilesInDir(const std::string &dir, const std::string &fileTemplate, const std::string &addString, Int_t nofFiles, Int_t fileSizeLimit=50000, Int_t nofEvents=1000)
Definition: CbmHaddBase.cxx:74
CbmHaddBase::CloseFilesFromList
static void CloseFilesFromList(TList *fileList)
Definition: CbmHaddBase.cxx:163
CbmHaddBase
Definition: CbmHaddBase.h:22
CbmHaddBase::GetGoodFiles
static vector< string > GetGoodFiles(const string &pattern, Int_t fileSizeLimit, Int_t nofEvents)
Definition: CbmHaddBase.cxx:34