Is it possible to loop over all Histograms in a TFile?

Hi there,

I have a question regarding a TFile. Is there a way to loop over all histograms in the TDirectories, within a TFile?

The structure of my TFile is as follows:

     TDirectory "Dir1"
                                    TH1 "dir1_histo1"
       TDirectory "Dir2"
                                    TH1 "dir2_histo1"

I started looking at the BaBar website and have constructed the following; But I think I would also benefit for other people comments.

Many thanks,



//read TFile
TFile *infile = new TFile(inputfile);

//loop counter(s)
 int i=0;
 int j=0;

  TIter nextkey(gDirectory->GetListOfKeys());
  while (key = (TKey*)nextkey()) {
    std::cout << "i: " << i << std::endl;
    obj = key->ReadObj();
    std::string name = obj->GetName();
    std::cout << "name: " << name << std::endl;
    if ( obj->IsA()->InheritsFrom("TDirectory") ){
                                                                                                                                                                                                  TIter nextkey(gDirectory->GetListOfKeys());                                                                                                                                                     
                 while (key = (TKey*)nextkey()) {                                                                                                                                                                
                 obj = key->ReadObj();                                                                                                                                                                         
                 if (obj->IsA()->InheritsFrom("TH1")) {                                                                                                                                                        
                 h = (TH1*)obj;                                                                                                                                                                              
                 std::cout << h->GetName() << std::endl;                                                                                                                                                     
                 std::cout << "j: " << j << std::endl;                                                                                                                                                         


What you do is ok for 1 or 2 levels down directories. If you want to process deeper levels, implement a function for one directory only and call it recursively.



Thanks for the quick reply. I will implement a function for reading each TH1 in each TTree of my input TFile. But form the moment I’ll still testing my code.

I have another question. I can now loop over the histograms in a TFile, I can then push then [ TH1’s ] back into a vector, which i then can write to a new TTree created in a new output TFile. Unfortunately, I find the histograms in this output TFile filled with nonsense! Is there anything I should be doing different in the code in I’ve marked with (£££) below?

Many thanks,


TFile *outfile = new TFile(“OutFile.root”, “RECREATE”);
infile = new TFile(inputfile);

if (infile) {
std::cout << "HistoNorm> input file open. " << std::string(inputfile) << std::endl;
} else {std::cout << "HistoNorm> could not open input file. "<< std::endl; exit(1);}

TTree t1 = (TTree)gDirectory->Get(“1”);
TIter nextkey(gDirectory->GetListOfKeys());
while (key = (TKey*)nextkey() ){
obj = key->ReadObj();
if (obj->IsA()->InheritsFrom(“TH1”)) {
h = (TH1*)obj;
std::cout << h->GetTitle() << std::endl;
Hint = h->Integral();
std::cout << "Before: " << Hint << std::endl;
h->Scale( 1.0/Hint );
Hint = h->Integral();
std::cout << “After:” << Hint << std::endl;
newh.push_back( (TH1*)h->Clone(“copy”) );

TH1 *myhisto;
char hname[50];
int p=0;

TTree *tree1 = new TTree(“data”, “Normalised”);

for( ihisto = newh.begin(); ihisto != newh.end(); ++ihisto ){
myhisto = (*ihisto);
(£££) tree1->Branch(hname, &myhisto, hname); //<- tree tree1 filled with histograms, but nothing contained within then.

if ( outfile ) outfile->Close();



When creating a branch, you need to pass the address of a pointer where the TTree will find the object. When doing tree->Fill, the tree looks up again and dereference the pointer. Since you always pass the same pointer to all the branches, all the branches ends up pointing to the same histograms.

In addition you have the pattern:for( ihisto = newh.begin(); ihisto != newh.end(); ++ihisto ){ tree1->Branch(hname, &myhisto, hname); tree1->Fill(); ++p; } where you Fill the tree after adding each branches. This results in unbalanced tree where the first branch has nhisto entries, the 2nd branch has nhisto-1 entries, the 3rd branch has nhisto-2. (And due to your re-use of the pointer, the entry n of the 1st branch, n-1 of the 2nd branch, n-2 of the 3rd branch, etc. has the same values).

[quote]I find the histograms in this output TFile filled with nonsense![/quote]How did you assert this?

However, a better question is, “what are you trying to achieve by putting these histogram in a TTree”, “how do you plan on using them”?

Ps. You might also want to re-read the User Guide’s chapter on TTrees.