Getting Histograms from ROOT files with TChain

Hi All,

I have a little method that does this

[code] TFile* m_f = TFile::Open(“InFileName”);
TFile* outF = new TFile(“outFileName”, “RECREATE”);

TH1D* hist = (TH1D*)m_f->Get("histName");

hist->Write();

m_f->Close();

outF->Close();[/code]

Where the input file is a .root file merged from many .root files with identical structures containing histograms, using the hadd() method.

I can no longer do this due to disk spaces, how can I substitute the merged input file with a TChain, adding all of the files? For example:

[code] TChain* m_f = new TChain("");
m_f->Add(File1);
m_f->Add(File2);
TFile* outF = new TFile(“outFileName”, “RECREATE”);

TH1D* hist = (TH1D*)m_f->GetHistogram("histName");

hist->Write();

m_f->Close();

outF->Close();[/code]

I have tried this, however the GetHistogram() method from the TTree class, where TChain inherits from, cannot be used like in the first example, where Get() belongs to TDirectoryFile, where TFile inherits from.

Thanks in advance for the help,

Cheers
Jason

Hi All,

For those who are interested, I have found a little work around, written in a separate method without using TChain. Hence this would also work as a work around for people who wants to avoid running hadd everytime they get a new set of files.

I created a .txt (inputs.txt) file containing the paths to all the files I want in the TChain, 1 line per path as follows:

/Directory/file1.root /Directory/file2.root

Then I write a method to put all these paths into a vector of strings:

[code]std::vectorstd::string GetFileList(const char* fileName)
{
std::vectorstd::string fileList;

char infile[1000];
sprintf(infile, “%s.txt” , fileName);

std::string line;
std::ifstream ifs(infile);

while(std::getline(ifs, line))
{
fileList.push_back(line);
}

return fileList;
}[/code]

I then do this:

[code]void GetHistTest(){

std::vectorstd::string FileList = GetFileList(“inputs”);

TFile* m_f;
TH1D* dummyHist;

for (unsigned int iFile=0; iFile<1; ++iFile)
{
m_f = TFile::Open(FileList[iFile].c_str());
dummyHist = (TH1D*)m_f->Get(“histName”);
}
TH1D* outHist = (TH1D*)dummyHist->Clone();

for (unsigned int iFile=1; iFile<FileList.size(); ++iFile)
{
m_f = TFile::Open(FileList[iFile].c_str());
dummyHist = (TH1D*)m_f->Get(“histName”);
outHist->Add(dummyHist);
}

m_f->Close();

TFile* outF = new TFile(“outFile.root”, “RECREATE”);
outHist->Write();
outF->Close();

}[/code]

Hope this is helpful to whoever wants to do the same thing.
Cheers,
Jason

Hi

I have a basic question related with this: I have a root file with few folders and subfolders and many histograms in each folder.

Does the TChain add all the histograms from all the input files in just one histogram?

I can do the same solution as pointed here, loop on all the files and add the histogram I want, but if I want many, this solution is not practical… does it the normal TChain work for this?

Cheers
Salva

By the way… what’s wrong with this ?

I just tried to chain 2 files which have the same structure. In run_302956/IDAlignMon/ExtendedTracks_all/Residuals ther are only histograms.

Cheers
Salva

root [1] TChain chain(“run_302956/IDAlignMon/ExtendedTracks_all/Residuals”);
root [2] chain.Add("/afs/cern.ch/user/a/atlidali/w0/calibLoop/Tier0/data16_13TeV/calibration_IDTracks/00302956/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.c0/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.Block01.c0._0001.1")
(Int_t) 1
root [3] chain.Add("/afs/cern.ch/user/a/atlidali/w0/calibLoop/Tier0/data16_13TeV/calibration_IDTracks

root [1] TChain chain(“run_302956/IDAlignMon/ExtendedTracks_all/Residuals”);
root [2] chain.Add("/afs/cern.ch/user/a/atlidali/w0/calibLoop/Tier0/data16_13TeV/calibration_IDTracks/00302956/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.c0/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.Block01.c0._0001.1")
(Int_t) 1
root [3] chain.Add("/afs/cern.ch/user/a/atlidali/w0/calibLoop/Tier0/data16_13TeV/calibration_IDTracks/00302956/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.c0/data16_13TeV.00302956.calibration_IDTracks.idalignmerge.ROOT_MON.Iter3.Block00.c0._0001.1")
(Int_t) 1
root [4] chain.GetNbranches()

*** Break *** segmentation violation

===========================================================
There was a crash.
This is the entire stack trace of all threads:

#0 0x00007f92d5ab47be in waitpid () from /lib64/libc.so.6
#1 0x00007f92d5a465c9 in do_system () from /lib64/libc.so.6
#2 0x00007f92d6a2dc5a in TUnixSystem::StackTrace() () from /cvmfs/atlas.cern.ch/repo/sw/software/x86_64-slc6-gcc49-opt/20.7.5/sw/lcg/releases/LCG_81c/ROOT/6.04.14/x86_64-slc6-gcc49-opt/lib/libCore.so
#3 0x00007f92d6a2fc2c in TUnixSystem::DispatchSignals(ESignals) () from /cvmfs/atlas.cern.ch/repo/sw/software/x86_64-slc6-gcc49-opt/20.7.5/sw/lcg/releases/LCG_81c/ROOT/6.04.14/x86_64-slc6-gcc49-opt/lib/libCore.so
#4
#5 0x00007f92d2423758 in TDirectoryFile::WriteObjectAny(void const*, char const*, char const*, char const*, int) () from /cvmfs/atlas.cern.ch/repo/sw/software/x86_64-slc6-gcc49-opt/20.7.5/sw/lcg/releases/LCG_81c/ROOT/6.04.14/x86_64-slc6-gcc49-opt/lib/libRIO.so
#6 0x00007f92c8a6b7cb in TChain::LoadTree(long long) () from /cvmfs/atlas.cern.ch/repo/sw/software/x86_64-slc6-gcc49-opt/20.7.5/sw/lcg/releases/LCG_81c/ROOT/6.04.14/x86_64-slc6-gcc49-opt/lib/libTree.so
#7 0x00007f92c8a688ef in TChain::GetNbranches() () from /cvmfs/atlas.cern.ch/repo/sw/software/x86_64-slc6-gcc49-opt/20.7.5/sw/lcg/releases/LCG_81c/ROOT/6.04.14/x86_64-slc6-gcc49-opt/lib/libTree.so
#8 0x00007f92c454e035 in ?? ()

A TChain is a collection of files containg TTree objects.

If you want to add histograms from some ROOT files, try the “hadd” standalone utility.