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