Reading Histograms from multiple .root files and plotting them on the same Canvas

Hi Dear ROOTers,

I have some 50-100 .root files with histograms in each file. I have to read a histogram from each file, all histograms have the same name. The path to histograms is “GenericPropagation/mydetector/drift_time_histo”. So in total i need to extract 50-100 histograms, and plot them on the same canvas. Also i need to properly rebin and do gaussian fit for each histogram and plot the Mean values with errors against electric filed lets say. I am very new to root, i tried to loop over .root files to read the histograms but it totally dont work. can any one help me in this regard? many thanks in advance. kind regards, Faiz

Welcome to the ROOT forum

Can you provide the code you have already?

TFile *fname[number_of_files];
fname[0] = new TFile(path_to_files); and so on

for(loop_variable)
fname[loop_variable]->Get(histogram_name);

@couet thank you so much. I have a code for that i got help from ChatGPT. it shows gives the value for only the first file and then i dont understand what happens. I am sorry for this statement but i dont have much experience that is why…
i have the 47 .root files with names volatage_%dV where %d are the voltage values provided in the test.txt file and V is the unit of voltage .text and .root files are in the current directory .
electric field is defined by the formula E=V[i]/0.05cm where V[i] are the corresponding values from the test.text file. The code is

void anaroot() {
    // Read voltage values from test.txt
    std::ifstream voltageFile("test.txt");
    if (!voltageFile.is_open()) {
        std::cerr << "Error opening test.txt" << std::endl;
        return;
    }

    std::vector<double> voltageValues;
    double voltage;
    while (voltageFile >> voltage) {
        voltageValues.push_back(voltage);
    }
    voltageFile.close();

    TCanvas* c = new TCanvas("c", "Histograms", 800, 600);
    TLegend* legend = new TLegend(0.6, 0.6, 0.9, 0.9);

    std::vector<double> meanValues;
    std::vector<double> meanErrors;

    // Loop over voltage values
    for (size_t i = 0; i < voltageValues.size(); ++i) {
        TString rootFileName = Form("volatage_%.0fV.root", voltageValues[i]);
        TFile* rootFile = TFile::Open(rootFileName);
        if (!rootFile) {
            std::cerr << "Error opening " << rootFileName << std::endl;
            continue;
        }

        TH1F* histo = (TH1F*)rootFile->Get("GenericPropagation/mydetector/drift_time_histo");
        if (!histo) {
            std::cerr << "Error getting histogram from " << rootFileName << std::endl;
            rootFile->Close();
            continue;
        }

        // Superimpose histograms
        if (i == 0) {
            histo->Draw();
        } else {
            histo->Draw("SAME");
        }

        // Gaussian fit
        TF1* gaussianFit = new TF1("gaussianFit", "gaus", histo->GetMean() - 2 * histo->GetRMS(), histo->GetMean() + 2 * histo->GetRMS());
        histo->Fit(gaussianFit, "Q");
        double mean = gaussianFit->GetParameter(1);
        double meanError = gaussianFit->GetParError(1);
        delete gaussianFit;

        // Print mean values with errors
        std::cout << "Voltage: " << voltageValues[i] << " V\tMean: " << mean << " ± " << meanError << std::endl;

        // Store mean values and errors
        meanValues.push_back(mean);
        meanErrors.push_back(meanError);

        // Add entry to legend
        TString legendEntry = Form("%.0f V", voltageValues[i]);
        legend->AddEntry(histo, legendEntry, "l");

        rootFile->Close();
    }

    legend->Draw();
    c->Draw();

    // Plot mean values against electric field
    TCanvas* c2 = new TCanvas("c2", "Mean vs. Electric Field", 800, 600);
    TGraphErrors* meanVsField = new TGraphErrors(voltageValues.size());
    for (size_t i = 0; i < voltageValues.size(); ++i) {
        double electricField = voltageValues[i] / 0.05; // E = V / 0.05
        meanVsField->SetPoint(i, electricField, meanValues[i]);
        meanVsField->SetPointError(i, 0, meanErrors[i]); // Assuming no error in electric field
    }
    meanVsField->SetTitle("Mean vs. Electric Field");
    meanVsField->GetXaxis()->SetTitle("Electric Field (V/cm)");
    meanVsField->GetYaxis()->SetTitle("Mean Value");
    meanVsField->Draw("AP");

    c2->Draw();
}

the output and error it gives is as following

Processing anaroot.C...
Voltage: 10 V	Mean: 532.493 ± 0.113499

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007f0acc27860c in waitpid () from /lib64/libc.so.6
#1  0x00007f0acc1f5f62 in do_system () from /lib64/libc.so.6
#2  0x00007f0accfbc4ed in TUnixSystem::StackTrace() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#3  0x00007f0accfbbea4 in TUnixSystem::DispatchSignals(ESignals) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#4  <signal handler called>
#5  0x00007f0acce6f020 in TAttLine::Copy(TAttLine&) const () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#6  0x00007f0aac613579 in TLegend::PaintPrimitives() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libGraf.so
#7  0x00007f0aac756eea in TPad::Paint(char const*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#8  0x00007f0acd30ad43 in ?? ()
#9  0x00007f0acccb0e60 in vtable for std::basic_ifstream<char, std::char_traits<char> > () from /cvmfs/sft.cern.ch/lcg/releases/gcc/12.1.0-57c96/x86_64-centos7/lib64/libstdc++.so.6
#10 0x0000000000000000 in ?? ()
===========================================================


The lines below might hint at the cause of the crash. If you see question
marks as part of the stack trace, try to recompile with debugging information
enabled and export CLING_DEBUG=1 environment variable before running.
You may get help by asking at the ROOT forum https://root.cern/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at https://root.cern/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#5  0x00007f0acce6f020 in TAttLine::Copy(TAttLine&) const () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#6  0x00007f0aac613579 in TLegend::PaintPrimitives() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libGraf.so
#7  0x00007f0aac756eea in TPad::Paint(char const*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#8  0x00007f0acd30ad43 in ?? ()
#9  0x00007f0acccb0e60 in vtable for std::basic_ifstream<char, std::char_traits<char> > () from /cvmfs/sft.cern.ch/lcg/releases/gcc/12.1.0-57c96/x86_64-centos7/lib64/libstdc++.so.6
#10 0x0000000000000000 in ?? ()
===========================================================


Root > 
 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007f0acc27860c in waitpid () from /lib64/libc.so.6
#1  0x00007f0acc1f5f62 in do_system () from /lib64/libc.so.6
#2  0x00007f0accfbc4ed in TUnixSystem::StackTrace() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#3  0x00007f0accfbbea4 in TUnixSystem::DispatchSignals(ESignals) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#4  <signal handler called>
#5  0x00007f0acce6f020 in TAttLine::Copy(TAttLine&) const () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#6  0x00007f0aac613579 in TLegend::PaintPrimitives() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libGraf.so
#7  0x00007f0aac75747e in TPad::PaintModified() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#8  0x00007f0aac71a55a in TCanvas::Update() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#9  0x00007f0aaab9e3e8 in TRootCanvas::HandleContainerConfigure(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#10 0x00007f0aaaa8b064 in TGFrame::HandleEvent(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#11 0x00007f0aaaa21648 in TGClient::HandleEvent(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#12 0x00007f0aaaa21c05 in TGClient::ProcessOneEvent() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#13 0x00007f0aaaa21c4a in TGClient::HandleInput() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#14 0x00007f0accfbb748 in TUnixSystem::DispatchOneEvent(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#15 0x00007f0acceca92c in TSystem::Run() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#16 0x00007f0acce62473 in TApplication::Run(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#17 0x00007f0acd4423d3 in TRint::Run(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libRint.so
#18 0x00000000004011dd in main ()
===========================================================


The lines below might hint at the cause of the crash. If you see question
marks as part of the stack trace, try to recompile with debugging information
enabled and export CLING_DEBUG=1 environment variable before running.
You may get help by asking at the ROOT forum https://root.cern/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at https://root.cern/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#5  0x00007f0acce6f020 in TAttLine::Copy(TAttLine&) const () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#6  0x00007f0aac613579 in TLegend::PaintPrimitives() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libGraf.so
#7  0x00007f0aac75747e in TPad::PaintModified() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#8  0x00007f0aac71a55a in TCanvas::Update() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGpad.so
#9  0x00007f0aaab9e3e8 in TRootCanvas::HandleContainerConfigure(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#10 0x00007f0aaaa8b064 in TGFrame::HandleEvent(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#11 0x00007f0aaaa21648 in TGClient::HandleEvent(Event_t*) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#12 0x00007f0aaaa21c05 in TGClient::ProcessOneEvent() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#13 0x00007f0aaaa21c4a in TGClient::HandleInput() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/lib/libGui.so
#14 0x00007f0accfbb748 in TUnixSystem::DispatchOneEvent(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#15 0x00007f0acceca92c in TSystem::Run() () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#16 0x00007f0acce62473 in TApplication::Run(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libCore.so
#17 0x00007f0acd4423d3 in TRint::Run(bool) () from /cvmfs/sft.cern.ch/lcg/releases/ROOT/6.28.00-a8528/x86_64-centos7-gcc12-opt/bin/../lib/libRint.so
#18 0x00000000004011dd in main ()
===========================================================

The source to root is source /cvmfs/clicdp.cern.ch/software/allpix-squared/latest/x86_64-centos7-gcc12-opt/setup.sh
Thank you and apologies for my probable stupid question …

@srikanta thank you very much but i am not in a stage to understand so specific and oriented hints. i am sorry :slight_smile:

Your code cannot be run as the data files are missing. Do not trust too much ChatGPT it often gives wrong results.
What you should do is loop over the 47 files. At each iteration, you open the next file using TFile and you get your histogram in that file using Get(…) as @srikanta showed.

Thank you @couet, starting with the hints given by @srikanta I got a code that really works well for extracting the histograms and superimposing them in the same canvas.

    TLegend* legend = new TLegend(0.8, 0.3, 0.9, 0.9);
    
    const int numFiles = 47;
    std::vector<int> voltageValues;

    std::ifstream inputFile("test.csv");
    if (!inputFile.is_open()) {
        std::cerr << "Error opening test.csv" << std::endl;
        return;
    }

    std::string line;
    while (std::getline(inputFile, line)) {
        std::stringstream ss(line);
        std::string valueStr;
        while (std::getline(ss, valueStr, ',')) {
            int value = std::atoi(valueStr.c_str());
            voltageValues.push_back(value);
        }
    }

    inputFile.close();
    
    std::vector<TFile*> files;
    TH1F* firstHisto = nullptr; // To adjust the range for the first histogram
    
    for (int i = 0; i < numFiles; i++) {
        std::string fileName = Form("volatage_%dV.root", voltageValues[i]);
        TFile* file = TFile::Open(fileName.c_str());
        
        if (file) {
            files.push_back(file);
            TH1F* histo = (TH1F*)file->Get("GenericPropagation/mydetector/drift_time_histo");
            
            if (histo) {
                if (i == 0) {
                    histo->Draw();
                    firstHisto = histo;
                } else {
                    histo->Draw("SAME");
                }
                histo->SetLineColor(i + 1); // Set different colors for histograms
                histo->SetLineWidth(2);     // Set line width
                
                if (i == 0) {
                    histo->GetXaxis()->SetRangeUser(0, 550); // Adjust x-axis range for the first histogram
                }
                
                 // Fit Gaussian to the histogram
                TF1* gaussFit = new TF1("gaussFit", "gaus", 0, 600); // Gaussian fit function
                histo->Fit(gaussFit, "R"); // Fit the histogram
                double mean = gaussFit->GetParameter(1); // Mean of the Gaussian
                double meanError = gaussFit->GetParError(1); // Error on the mean
                
                std::cout << "Voltage " << voltageValues[i] << "V: Mean = " << mean << " ± " << meanError << std::endl;

                // Add histogram entry to legend
                legend->AddEntry(histo, Form("Voltage %dV", voltageValues[i]), "l");
            }
        }
    }
    
    if (firstHisto) {
        c->Update();
        firstHisto->GetXaxis()->SetRangeUser(0, 600); // Adjust x-axis range for the first histogram again
    }
    
    legend->Draw();
    c->Draw();
1 Like