Looping over root files in a folder


Please read tips for efficient and successful posting and posting code

_ROOT Version: 6.26/11
_Platform: Scientific Linux 6.7
Compiler: Not Provided


Hi, I am quite new to ROOT, so please apologise any mistakes.
I have a lot of .root files (260) inside a folder, each with a tree inside called “events” (NanoAOD for those who know) and I wrote a macro to extract data from the tree of a single file and build some histograms, as you can see below

TFile *inFile = TFile::Open("/path/to/folder/file_name.root", "READ");

TTreeReader myReader("Events", inFile);
//plus a bunch of TTreeReaderValue or TTreeReaderArray

while(myReader.Next()){
//perform some calculation and build histograms
}

As you can see I opened only one file, but now I want to loop over all the files in the folder and read data from all of them; the names of the tree and the branches don’t change across the different file, so the only thing I have to modify is the first line, but i don’t know how to do that.
All the .root files have quite long and random name (a sequence of roughly 30 alpha-numerical characters).

You may try the following code:

{
TChain *fCh = new TChain("Events");
fCh->Add("/path/to/folder/*.root");
//fCh->Print();

Int_t Branch;

fCh->SetMakeClass(1);
fCh->SetBranchAddress("BranchName", &Branch);

TH1F *histBranch = new TH1F("histBranch","histBranch", 4096,0,4096);

Long64_t jentry;
Long64_t nentries = fCh->GetEntriesFast();

for (jentry = 0; jentry < nentries; jentry++) {

        Long64_t ientry = fCh->LoadTree(jentry);
        if (ientry < 0) break; // we are done

        fCh->GetEntry(jentry);

        if(Branch > 0) histBranch->Fill(Branch);
}
histBranch->Draw();
}

Thanks, the code you provided worked well. I modified it a little to incorporate a TreeReader. In this example I define a TreeReaderValue to get the nMuon branch values and plot them into a histogram and the code seems to work fine. Is this the proper way to do it?

TChain *fCh = new TChain("Events");
fCh->Add("/path/to/folder/*.root");
//fCh->Print();

fCh->SetMakeClass(1);
TH1F *histBranch = new TH1F("histBranch","histBranch", 100,0,8);

TTreeReader myReader(fCh);
TTreeReaderValue<Int_t> nMuon(myReader, "nMuon");

while(myReader.Next()){
  histBranch->Fill(*nMuon);
}

histBranch->Draw();

The only thing which is unclear to me is the SetMakeClass() command; if I comment this line the histogram doesn’t change. I’ve read the documentation, but i didn’t understand what it does. Is it normal that the result doesn’t change?

Hi @Michelangelo ,

I like the answer above: thanks @ajaydeo !

If I understand correctly (please correct me if I am wrong!), you are dealing with CMS NanoAOD, which means fundamental types and arrays thereof. In that case, MakeClass is not really needed since there is no class in the data model (you would need that if in your column you had objects, for example CMS AOD or MiniAOD).

As for your analysis, I could also propose an alternative approach which is based on the modern way to analyse event data, RDataFrame.

// To use all of your cores and run the analysis in multithreaded mode,
// just uncomment the following line:
// ROOT::EnableImplicitMT();
ROOT::RDataFrame df("Events", "/path/to/folder/*.root");
auto histBranch = df.Histo1D({"histBranch","histBranch",100,0,8}, "nMuon");
histBranch->Draw();

I hope this speeds you up!

Cheers,
Danilo

Hi Danilo,
you’re right, I am dealing with CMS NanoAOD. Thanks for the explanation of the MakeClass command and thanks also for the RDataFrame suggestion, I will check it out.

1 Like