Rebinning all the histograms in root file to new root file

Dear All,

I have root file with directory called “bin4mu” and this directory containg a lot of histograms “TH1D”.
I need to rebin all the histograms in the old root file and write them to a new root file under directory called “bin4mu”.

Here what I’m doing

#include "TFile.h"
#include "TKey.h"
#include "TCollection.h"
#include "TIterator.h"
#include "TString.h"
#include "TH1.h"
#include "TH2.h"
#include "TCanvas.h"
#include <iostream>

void rebin_histos(){

  TFile* file = TFile::Open("shapeBDTG_4mu.root");
  TFile* fileout = TFile::Open("shapeBDTG_4mu_rebinned.root","RECREATE");

  file->cd("bin4mu");
  file->ls();

  TIter next(file->GetListOfKeys());
  TKey* key0;

  while((key0=(TKey*)next())){
    cout<<"step1"<<endl;
    auto obj = key0->ReadObj();
    cout<<"step2"<<endl;
    if(obj->InheritsFrom("TH2")) continue;
    cout<<"step3"<<endl;
    TH1D* h = (TH1D*)obj;
    cout<<"step4"<<endl;
    h->Rebin(2);
    cout<<"step5"<<endl;
    fileout->mkdir("bin4mu/");
    fileout->cd("bin4mu/");
    h->Write();
   }
  fileout->Write();
  file->Close();
}

But I have segmentation violation in the step of h->Rebin(2);
I don’t know what is the problem.

Regards
Reham
__
Please read tips for efficient and successful posting and posting code

ROOT Version: Not Provided
Platform: Not Provided
Compiler: Not Provided


Hi,
You should check if the read object is a TH1D so you can run rebin.
I would do :

TH1D* h = dynamic_cast<TH1D*>(obj);
if (!h) continue; 

Lorenzo

Thanks Lorenzo,

I added the check you mentioned and it is partially working.
Even all the histograms in the input root file are TH1D, the loop don’t pass this continue statement if (!h) continue;
I attached the input root file.
There are some histograms with zero entries but I don’t think this is the problem.

I don’t know what is the problem.

Reham
shapeBDTG_4mu.root (402.1 KB)

This works for me and I see only TH1D objects. In your case you might have TDirectory objects.

TFile* file = TFile::Open("shapeBDTG_4mu.root");
 
file->cd("bin4mu");
file->ls();

auto keyList = gDirectory->GetListOfKeys();
for (auto key0 : *keyList) {
   auto obj = ((TKey*)key0)->ReadObj();
   cout << obj->ClassName() << endl;
}

It is strange, because for me the loop stops at step3 in the cout statements and I have an empty output root file.
Let me post again here my macro may be I didn’t get something you already mentioned.

#include "TFile.h"
#include "TKey.h"
#include "TCollection.h"
#include "TIterator.h"
#include "TString.h"
#include "TH1.h"
#include "TH2.h"
#include "TCanvas.h"
#include <iostream>

void rebin_histos(){

  TFile* file = TFile::Open("shapeBDTG_4mu.root");
  TFile* fileout = TFile::Open("shapeBDTG_4mu_rebinned.root","RECREATE");

  file->cd("bin4mu");
  file->ls();
 TIter next(file->GetListOfKeys());
  TKey* key0;

  while((key0=(TKey*)next())){
    //TObject* obj = (TObject*)key0;
    cout<<"step1"<<endl;
    auto obj = key0->ReadObj();
    cout<<"step2"<<endl;
    if(obj->InheritsFrom("TH2")) continue;
    cout<<"step3"<<endl;
    //TH1D* h = (TH1D*)obj;
    TH1D* h = dynamic_cast<TH1D*>(obj);
    if (!h) continue;
    cout<<"step4"<<endl;
    h->Rebin(2);
    cout<<"step5"<<endl;
    fileout->mkdir("bin4mu/");
    fileout->cd("bin4mu/");
    h->Write();
   }
  fileout->Write();
  file->Close();
}

The following works for me:

        TFile* outfile = TFile::Open("shapeBDTG_4mu_rebinned.root", "RECREATE");
        TFile* infile = TFile::Open("shapeBDTG_4mu.root", "READ");


        TKey* key;
        TIter nextkey(gDirectory->GetListOfKeys());
        while ((key = static_cast<TKey*>(nextkey())))
        {
                TObject* obj = key->ReadObj();
                std::string name = obj->GetName();
                if ( obj->IsA()->InheritsFrom("TDirectory") && name == "bin4mu") // loop over TDirectory derivatives
                {
                        printf("Found a TDirectory (or its derivative) with a name \"%s\"...\n", name.c_str());
                        outfile->mkdir(name.c_str());
                        infile->cd(obj->GetName());

                        TIter nextkey1(gDirectory->GetListOfKeys());
                        TKey* key1;
                        while ((key1 = static_cast<TKey*>(nextkey1()))) // loop over objects in that TDirectory derivative
                        {
                                TObject* obj1 = key1->ReadObj();
                                if (obj1->IsA()->InheritsFrom("TH1") && !obj1->IsA()->InheritsFrom("TH2")) // only 1D histograms
                                {
                                        TH1* h = static_cast<TH1*>(obj1);
                                        if (h)
                                        {
                                                printf("\tFound a TH1 (or its derivative) with a name \"%s\", rebinning...\n", h->GetName());
                                                h->Rebin(2);
                                                outfile->cd(name.c_str());
                                                h->Write();
                                        }
                                }
                        }
                }
        }
        outfile->Write();
        outfile->Close(); infile->Close();

Yes it works good.
Thanks a lot.

The wrong line you were having is:
file->GetListOfKeys()

You should use gDirectory->GetListOfKeys()

Lorenzo

Thanks a lot :grinning:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.