/* * Merge root histograms into one histogram file. * Each histogram file must contain the same histograms and ntuples * in the same directory structure. * yuji@fnal.gov * * Supported objects: TH1F, TH2F, TNtuple * All variables in TNtuple should be float type (probably) * * Usage: ].L hmrg.C+ * ]merge() * * Time-stamp: <2004-05-31 16:25:40 yuji> */ #include #include #include "TROOT.h" #include "TKey.h" #include "TF1.h" #include "TH2.h" #include "TFile.h" #include "TNtuple.h" using std::cout; using std::cerr; using std::endl; //gROOT->Reset(); const char *infile[] = { "hoge1.root", "hoge2.root" }; const char *outfile="merged.root"; // prototype declaration void dirScan(TDirectory*); // Global variables TFile* fout; // // duplicate TNtuple object // TNtuple* appendTNtuple(TNtuple* ntpl0, TNtuple* ntpl) { TNtuple* tnew; if (!ntpl0) { char buff[4096]; buff[0]=0; // make var list TObjArray* br=ntpl->GetListOfBranches(); for(int idx=0; ; ++idx) { strncat(buff, br->At(idx)->GetName(), 4096); if ( idx+1 == br->GetEntries() ) break; strncat(buff, ":", 4096); } // create new ntuple but it's empty tnew= new TNtuple(ntpl->GetName(), ntpl->GetTitle(), buff); } else { tnew=ntpl0; } // append contents for(int idx=0; idxGetEntries(); ++idx) { ntpl->GetEvent(idx); tnew->Fill(ntpl->GetArgs()); } return tnew; } // // treat TDirectory object (output to fout) // void dirScan(TDirectory* dir1) { // make string of same name direcotry for fout const char* fname1=dir1->GetFile()->GetName(); // obtain filename of dir1 const char* path2=dir1->GetPath()+ strlen(fname1); // obtain pathname without filename char buff[1024]; strncpy(buff, fout->GetName(), 1024); strncat(buff, path2, 1024); dir1->cd(); // change searching directory TList* olist = gDirectory->GetListOfKeys(); for(int oidx=0; oidxGetSize(); ++oidx) { // get objects in this directory TKey* key=(TKey*)olist->At(oidx); // read object from key dir1->cd(); TObject* obj=key->ReadObj(); // show the object for debug // cout << dir1->GetPath() << "/" << obj->GetName() // << "(" << obj->ClassName() << ")" << endl; // TDirectory //////////////// if (!strcmp(obj->ClassName(), "TDirectory")) { TDirectory* tdObj=(TDirectory*)obj; // check if fout has the directory gDirectory->cd(buff); if (!gDirectory->GetKey(tdObj->GetName())) { gDirectory->mkdir(tdObj->GetName()); cout << "Create " << buff << "/" << tdObj->GetName() << endl; } // recursive call of dirScan dirScan(tdObj); } // endif TDirectory object // TH1F //////////////// if (!strcmp(obj->ClassName(), "TH1F")) { TH1F* th1fObj=(TH1F*)obj; // check if fout has the histo. gDirectory->cd(buff); TH1F* th1fObj2; if (!gDirectory->Get(th1fObj->GetName())) { th1fObj2=new TH1F(*th1fObj); cout << "Create " << buff << "/" << th1fObj->GetName() << endl; } else { th1fObj2=(TH1F*)(gDirectory->Get(th1fObj->GetName())); th1fObj2->Add(th1fObj); } } // endif TH1F object // TH2F //////////////////// if (!strcmp(obj->ClassName(), "TH2F")) { TH2F* th2fObj=(TH2F*)obj; // check if fout has the histo. gDirectory->cd(buff); TH2F* th2fObj2; if (!gDirectory->Get(th2fObj->GetName())) { th2fObj2=new TH2F(*th2fObj); cout << "Create " << buff << "/" << th2fObj->GetName() << endl; } else { th2fObj2=(TH2F*)(gDirectory->Get(th2fObj->GetName())); th2fObj2->Add(th2fObj); } } // endif TH2F object // Ntuple ///////////////// if (!strcmp(obj->ClassName(), "TNtuple")) { TNtuple* tnObj=(TNtuple*)obj; // check if fout has the histo. gDirectory->cd(buff); TNtuple* tnObj2; if (!gDirectory->Get(tnObj->GetName())) { appendTNtuple(NULL, tnObj); cout << "Create " << buff << "/" << tnObj->GetName() << endl; } else { tnObj2=(TNtuple*)(gDirectory->Get(tnObj->GetName())); appendTNtuple(tnObj2, tnObj); } } // endif TH2F object } // for oindx } // // main routine // int merge() { int nfiles=sizeof(infile)/sizeof(char**); fout= new TFile(outfile, "RECREATE"); for(int fidx=0; fidxGetName() << endl; dirScan(gDirectory); } fout->Write(); fout->Close(); return 0; }