Accessing all histograms inside a rootfile

Hi all,
I am generating a ROOT file with 2306 histograms in it and afterwards, I want to read the ROOT file to access each histogram to make a fit to each one of them.

I am trying with the following code snippet:

std::string inFileName = argv[1];
TFile *f = new TFile(inFileName.c_str());
TList *list = f->GetListOfKeys();
TFile *outFile = new TFile("myfile.root", "recreate");
TH1D *hist;
TIter iter(list); //or TIter iter(list->MakeIterator());
while(hist = (TH1D*)iter()){
    hist->Draw();
    hist->Write();
}
outFile->cd();
outFile->Write();
outFile->Close();

which is generating the output root file called myfile.root with all the histograms as TKeys instead of TH1Ds (as in the input file). Also, the histograms are not being displayed at all.

Please can someone help?
Cheers,
Ruina

Can’t you put a if(hist-ClassName() == “TH1D”) in your while loop? I would use this to filter out the TObject you get and properly cast it to TH1D
Hope it helps

This:

TList *list = f->GetListOfKeys();
...
while(hist = (TH1D*)iter()){

is wrong. If you update it to be:

TList *list = f->GetListOfKeys();
...
while(hist = dynamic_cast<TH1D*>(iter())){

you will notice that the loop is never executed.
You need something like:

std::string inFileName = argv[1];
TFile *f = new TFile(inFileName.c_str());
TList *list = f->GetListOfKeys();
TFile *outFile = new TFile("myfile.root", "recreate");
TKey *key;
TIter iter(list); //or TIter iter(list->MakeIterator());
static TString classname("TH2D");
while(key = (TKey*)iter()) {
    if (key->GetClassName() == classname) {
       TH2D *hist = (TH2D*)key->ReadObject();
       if (hist) {
          output->WriteTObject(hist);
          delete hist;
       }
    }
}
outFile->cd();
outFile->Write();
outFile->Close();

Note that I removed the Draw as I not sure ‘what’/‘how’ you want to draw. The original code did not even have time to refresh the screen with one histogram before it was replaced by the next one.

Using pcanal’s suggestion, I get the following warning and error which I don’t know how to solve :frowning:

root_forum.cpp:24:29: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
     while(key = (TKey*)iter()) {
                             ^
root_forum.cpp:26:38: error: 'class TKey' has no member named 'ReadObject'
             TH2D *hist = (TH2D*)key->ReadObject();

My code is in the attachment.
root_forum.cxx (808 Bytes)

I think the only reason I put Draw() here was to check if the histogram is accessible or not.

Sorry, I’m not sure I understand what you mean.

Unfortunately, this also does not work. I don’t get any compilation error (except that
hist->ClassName() == “TH1D”
didn’t work because ClassName() returns a const char and not a string) but the output file does not contain the histograms.

Sorry there was missing paranthesis and a type (ReadObject instead of ReadObj)

std::string inFileName = argv[1];
TFile *f = new TFile(inFileName.c_str());
TList *list = f->GetListOfKeys();
TFile *outFile = new TFile("myfile.root", "recreate");
TKey *key;
TIter iter(list); //or TIter iter(list->MakeIterator());
static TString classname("TH2D");
while((key = (TKey*)iter())) {
    if (key->GetClassName() == classname) {
       TH2D *hist = (TH2D*)key->ReadObj();
       if (hist) {
          output->WriteTObject(hist);
          delete hist;
       }
    }
}
outFile->cd();
outFile->Write();
outFile->Close();

Note that:

static TString classname("TH2D");
if (key->GetClassName() == classname) {

is completely different from

if (hist->ClassName() == “TH1D”)

The former, because ‘classname’ is a TString object will use a string based comparison (something like strcmp) while the later since both operand and char* will do a comparison of the pointer value and thus the equality will always be false.

Thank you for the correction! Yes, I noticed now in the ROOT documentation that ReadObj() and ReadObject() are different!
The parentheses warning is also solved but I don’t understand why they are required?

However, the output root file still does not contain any histograms. :worried:

I did not know that (abou the string comparison thing). Thanks for the info!

what does f->ls(); prints?

Sorry, guess I should have answered that question in my previous reply already.

root [0] 
Attaching file ../out/root_forum.root as _file0...
root [1] .ls
TFile** ../out/root_forum.root
 TFile* ../out/root_forum.root
root [2]

humm … the file is empty then …

Note can also use the ROOT command line tools to explore the content of a ROOT file.
At the shell prompt just do:

$ rootls myfile.root

and you will see what is inside that file.

Thanks for the tip, couet. However, the root command line tools were released with ROOT 6.06 while mine is an older version. Besides, I think it doesn’t matter as far as my question is concerned.

FWIW, groot provides (about) the same command-line tools, are independant of the ROOT version you’ve installed and can thus work alongside your usual ROOT setup:

(pick the root-ls-xxx-yyy.exe executable matching your OS/machine and voilà)

there’s also the uproot project which can provide the same facility (if you know Python).

doc:

Thanks for the info, sbinet!

But again, it does not help answer my original question.
:worried:

well, I could give you a program using Groot (but it would be in Go, not in C++ nor Python).

@Ruina Did you figure out why the file that you are using are ‘empty’? How do you generate them?

Thanks sbinet, but I need to figure out how to do it using C++.

The (input) file that I am using is not empty. It contains the histograms that I want to access one-by-one. It is the output file which is being rendered empty.

You were supposed to execute f->ls(); on the input file (it seems to me that you did it on the output file).