Reading and storing all histograms in a file

Hi,

I have a previously created root file with a lot of histograms. I want to read each histogram into a map indexed by it’s name, then close the file, do some processing on the histograms, and write them back into either the same or some other file. Reading and storing them looks good. But when I try to use them, I get a crash. Here is the code:

int main(int argc, char **argv)
{
  TApplication app("root",&argc,argv);  

  map<string,TH1F*> hists;

  {
    string const filename = "histograms.root";
    TFile file(filename.c_str());
    TIter iter(file.GetListOfKeys());
    TKey *key;
    while (key = (TKey*)iter()) {
      TObject *obj = key->ReadObj();
      TH1F *h = dynamic_cast<TH1F*>(obj);
      if (h) {
        hists[h->GetName()] = h;
      }   
    }   
  }

  for (map<string,TH1F*>::iterator it=hists.begin(); it != hists.end(); ++it) {
    TH1F *h = it->second;
    assert(h);
    cout <<h->GetTitle() <<" " <<h->GetEntries() <<endl;
  }
}

The crash happens when I use GetTitle() and GetEntries() on the histograms in the second loop. Notice that if I bring the TFile outside the local scope it works. So it seems to me that the stored histograms are somehow linked to the file. However I found no documentation stating that this is the case based on reading references for TFile, TIter, TKey, and TH1. I don’t want to keep the file open, I want to read everything and store it in memory, because I might want to overwrite the same file while still holding on the histogram objects.

Could someone please let me know what I’m doing wrong. I would also appreciate if someone could point me to the appropriate documentation explaining this behavior so I won’t get stumbled on something like this again.

Thanks!

Hi, You might try cloning the histograms:

root.cern.ch/root/html/TH1.html

grep for clone or copy

Thank you very much for your reply prdf. Unfortunately that does not solve the problem. I’ve tried all various combinations of Copy, Clone, and default constructor, none of which worked. This seems to be very simple and everyday thing, there must be something simple that I’m not doing/understanding correctly. Any more suggestions?

Here are the things I’ve tried:

[ul]
Using copy constructor: hists[h->GetName()] = new TH1F(*h);
Using Clone() without a new name: hists[h->GetName()] = (TH1F*)h->Clone();
Using Clone() with same name as old histogram: hists[h->GetName()] = (TH1F*)h->Clone(h->GetName());
Using Clone() with new name: hists[h->GetName()] = (TH1F*)h->Clone(("foo_"+string(h->GetName())).c_str());
Using Copy() into completely empty histogram: h->Copy(*(hists[h->GetName()] = new TH1F));
Using Copy() into histogram with same name and other parameters as the old one: h->Copy(*(hists[h->GetName()] = new TH1F(h->GetName(), h->GetTitle(), h->GetNbinsX(), h->GetMinimum(), h->GetMaximum())));
[/ul]

All of the above give the same crash…