00001 #include "HistMan.h"
00002
00003 #include <TSystem.h>
00004 #include <TKey.h>
00005 #include <TROOT.h>
00006 #include <TFile.h>
00007 #include <TH1.h>
00008 #include <TH2.h>
00009
00010
00011 #include <algorithm>
00012 #include <string>
00013 #include <vector>
00014 #include <iostream>
00015 #include <cassert>
00016 using namespace std;
00017
00018
00019
00020 vector<string> parse_path(const char* path)
00021 {
00022 vector<string> vs;
00023 string p(path);
00024 string::iterator it1=p.begin(), it2, done=p.end();
00025 for (it2=find(p.begin(),done,'/'); it2 != done; it2=find(it1,done,'/')) {
00026 if (it1==it2) {
00027 ++it1;
00028 continue;
00029 }
00030 string dir(it1,it2);
00031 if (dir != ".")
00032 vs.push_back(dir);
00033 it1 = it2+1;
00034 }
00035 if (it1 != it2) {
00036 string dir(it1,it2);
00037 if (dir != ".")
00038 vs.push_back(string(it1,it2));
00039 }
00040 return vs;
00041 }
00042
00043 TFolder& mkdir_p(TFolder& top, const char* path)
00044 {
00045 if (!path || path[0] == '\0') return top;
00046
00047 vector<string> vp = parse_path(path);
00048 TFolder* folder = ⊤
00049
00050 for (unsigned int ind=0; ind < vp.size(); ++ind) {
00051 const char* name = vp[ind].c_str();
00052 TFolder* tmp = dynamic_cast<TFolder*>(folder->FindObject(name));
00053 if (tmp) folder = tmp;
00054 else folder = folder->AddFolder(name,name);
00055 }
00056 return *folder;
00057 }
00058
00059 static int histcount = 0;
00060 HistMan::HistMan(TFolder* folder, bool own)
00061 : fFolder(folder)
00062 , fOwn(own)
00063 {
00064 if (!fFolder) {
00065 fFolder = new TFolder(Form("HistFolder%d",histcount),
00066 Form("Histogram Folder #%d",histcount));
00067 }
00068 fFolder->SetOwner(true);
00069 }
00070
00071 HistMan::HistMan(const char* base_directory)
00072 {
00073 fFolder = &this->BaseFolder();
00074 fFolder = &mkdir_p(*fFolder,base_directory);
00075 fOwn = false;
00076 fFolder->SetOwner(true);
00077 }
00078
00079 static TFolder* directory_to_folder(TDirectory& directory)
00080 {
00081 TFolder* folder = new TFolder(directory.GetName(),directory.GetName());
00082
00083 TList *l = directory.GetListOfKeys();
00084 if (!l) return folder;
00085
00086 TIter it(l->MakeIterator());
00087 TObject *obj=0;
00088 while ( (obj=it()) ) {
00089 TKey* key = dynamic_cast<TKey*>(obj);
00090 assert(key);
00091 obj = directory.Get(key->GetName());
00092 TDirectory* dir = dynamic_cast<TDirectory*>(obj);
00093 if (dir) {
00094 TFolder* fol = directory_to_folder(*dir);
00095
00096
00097
00098 folder->Add(fol);
00099 }
00100 else {
00101
00102
00103 folder->Add(obj);
00104 }
00105 }
00106 return folder;
00107 }
00108
00109
00110
00111 HistMan::HistMan(TFile& file, bool attach)
00112 {
00113 TDirectory* dir = dynamic_cast<TDirectory*>(file.Get("HistMan"));
00114 if (!dir) {
00115 cerr << "Failed to find HistMan folder in " << file.GetName() << endl;
00116 fFolder = &this->BaseFolder();
00117 fFolder = &mkdir_p(*fFolder,"");
00118 fOwn = false;
00119 fFolder->SetOwner(true);
00120 return;
00121 }
00122
00123 fFolder = directory_to_folder(*dir);
00124 if (attach) {
00125 fOwn = false;
00126 gROOT->Add(fFolder);
00127 }
00128 }
00129
00130 HistMan::HistMan(const char** file_list, const char** hist_list)
00131 {
00132 fFolder = &this->BaseFolder();
00133 fFolder = &mkdir_p(*fFolder,"");
00134 fOwn = false;
00135 fFolder->SetOwner(true);
00136
00137 for (int ifile=0; file_list[ifile]; ++ifile){
00138
00139
00140 if (gSystem->AccessPathName(file_list[ifile])) {
00141 cout << "HistMan: Warning: file " << file_list[ifile]
00142 << " does not exist!" << endl;
00143 continue;
00144 }
00145 TFile file(file_list[ifile]);
00146 if (!file.IsOpen()) {
00147 cout << "HistMan: Warning: problems opening file "
00148 << file_list[ifile] << endl;
00149 continue;
00150 }
00151 HistMan hm(file,false);
00152 for (int ihist=0; hist_list[ihist]; ++ihist){
00153
00154 TH1* hold = hm.Get<TH1>(hist_list[ihist]);
00155 if (!hold) {
00156 cout << "HistMan: Warning: histogram named "
00157 << hist_list[ihist] << " does not exist in file "
00158 << file_list[ifile] << endl;
00159 continue;
00160 }
00161
00162
00163
00164
00165 TH1* hnew = this->Get<TH1>(hist_list[ihist]);
00166 if (hnew)
00167 hnew->Add(hold);
00168 else{
00169 string hname_fullp(hist_list[ihist]);
00170 string::size_type pos = hname_fullp.rfind("/");
00171 string hname_path;
00172 if (pos < hname_fullp.length())
00173 hname_path = hname_fullp.substr(0,pos);
00174 else
00175 hname_path = "";
00176
00177 this->Adopt(hname_path.c_str(),dynamic_cast<TH1*>(hold->Clone()));
00178 }
00179 }
00180 file.Close();
00181 }
00182 }
00183
00184 HistMan::~HistMan()
00185 {
00186 if (fOwn) {
00187
00188 delete fFolder;
00189 }
00190 fFolder = 0;
00191 }
00192
00193 TFolder& HistMan::BaseFolder()
00194 {
00195 TFolder* folder = dynamic_cast<TFolder*>(gROOT->FindObjectAny("HistMan"));
00196 if (folder) return *folder;
00197
00198 folder = new TFolder("HistMan","Base Histogram Manager Folder");
00199 gROOT->Add(folder);
00200 return *folder;
00201 }
00202 void HistMan::RegisterWithRoot()
00203 {
00204 if (!fOwn) return;
00205 fOwn = false;
00206
00207 TFolder& base = this->BaseFolder();
00208 base.Add(fFolder);
00209 }
00210
00211 static void folder_to_directory(TFolder* folder, TDirectory& directory)
00212 {
00213 TDirectory*& prevdir = gDirectory, *dir = 0;
00214
00215 TObject* obj = directory.Get(folder->GetName());
00216 if (obj) {
00217 dir = dynamic_cast<TDirectory*>(obj);
00218 if (!dir) {
00219 cerr << "Non-directory object \"" << folder->GetName()
00220 << "\" already in directory\n";
00221 return;
00222 }
00223 }
00224 else
00225 dir = directory.mkdir(folder->GetName());
00226
00227 dir->cd();
00228
00229 TCollection* sf = folder->GetListOfFolders();
00230 if (!sf) {
00231 prevdir->cd();
00232 return;
00233 }
00234
00235 TIter it(sf->MakeIterator());
00236 obj=0;
00237 while ( (obj=it()) ) {
00238 TFolder *fol = dynamic_cast<TFolder*>(obj);
00239 if (fol) folder_to_directory(fol,*dir);
00240 else {
00241 dir->cd();
00242 obj->Write();
00243 }
00244 }
00245 prevdir->cd();
00246 }
00247
00248 void HistMan::WriteOut(TFile& file)
00249 {
00250 if (!fFolder) return;
00251 folder_to_directory(fFolder,file);
00252 }
00253 void HistMan::WriteOut(const char* filename)
00254 {
00255 TFile f(filename,"recreate");
00256 this->WriteOut(f);
00257 f.Close();
00258 }
00259
00260
00261 TObject* HistMan::Adopt(const char* dirpath, TObject* obj)
00262 {
00263 TH1* hist = dynamic_cast<TH1*>(obj);
00264 if (hist)
00265 hist->SetDirectory(0);
00266 TFolder* folder = &mkdir_p(*fFolder,dirpath);
00267 if (folder->FindObject(obj->GetName())) {
00268 cerr << "Object: " << dirpath << "/"
00269 << obj->GetName() << " already exists\n";
00270 delete obj;
00271 return 0;
00272 }
00273 folder->Add(obj);
00274 return obj;
00275 }
00276 bool HistMan::Fill1d(const char* pathname, Axis_t x, Stat_t w)
00277 {
00278 TObject* o = fFolder->FindObject(pathname);
00279 if (!o) o = fFolder->FindObjectAny(pathname);
00280 TH1* h = dynamic_cast<TH1*>(o);
00281 if (!h) {
00282 cerr << "Fill1d(\""<<pathname<<"\") failed lookup\n";
00283 return false;
00284 }
00285 h->Fill(x,w);
00286 return true;
00287 }
00288 bool HistMan::Fill2d(const char* pathname, Axis_t x, Axis_t y, Stat_t w)
00289 {
00290 TObject* o = fFolder->FindObject(pathname);
00291 if (!o) o = fFolder->FindObjectAny(pathname);
00292 TH2* h = dynamic_cast<TH2*>(o);
00293 if (!h) {
00294 cerr << "Fill2d(\""<<pathname<<"\") failed lookup\n";
00295 return false;
00296 }
00297 h->Fill(x,y,w);
00298 return true;
00299 }
00300
00301 bool HistMan::FillProfile(const char* pathname, Axis_t x, Axis_t y, Stat_t w)
00302 {
00303 TObject* o = fFolder->FindObject(pathname);
00304 if (!o) o = fFolder->FindObjectAny(pathname);
00305 TProfile* h = dynamic_cast<TProfile*>(o);
00306 if (!h) {
00307 cerr << "FillProfile(\""<<pathname<<"\") failed lookup\n";
00308 return false;
00309 }
00310 h->Fill(x,y,w);
00311 return true;
00312 }
00313
00314
00315 TObject* HistMan::GetObject(const char* pathname)
00316 {
00317
00318 if (!fFolder) return 0;
00319 vector<string> path = parse_path(pathname);
00320
00321 TFolder* folder = fFolder;
00322
00323 for (size_t ind=0; ind < path.size(); ++ind) {
00324
00325 TObject* o = folder->FindObject(path[ind].c_str());
00326 TFolder* f = dynamic_cast<TFolder*>(o);
00327 if (!f) return o;
00328 folder = f;
00329 }
00330 return 0;
00331 }
00332