How to save several trees in one file?

Hello!

I have a lot of events (> 100 000).
I want to calculate some values (integral, for example), draw graphs and save all this information in a tree.
Individual tree for each event.
If I write one tree in one file I waste a lot of time for open and close operations.
So, the better solution to save several trees in one file.

Previously, I used tree.Write().

Now, as I understand (TTree.Write() vs. TFile.Write()), I have to use tfile.Write().

But I get this message: Warning in <TFile::Write>: file not opened in write mode.
And my file is empty.

My code:

#include <iostream>
#include <string>
#include <iomanip>


#include "TGraph.h"
#include "TFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "TRandom.h"

using namespace std;

int main(int argc, char *argv[])
{
    TFile f_tree;

    string s_output_file = "/home/darkside/Vlad_Programs/test.root";
    const int events_per_file = 2;
    const int n_events = 2;
    const int samp_per_event = 100;

    vector<double> xv;
    for (int i = 0; i < samp_per_event; ++i)
    {
        xv.push_back(i);
    }

    TRandom rnd;


    for(int file_i = 0; file_i < n_events; file_i++)
    {
        vector<double> yv;
        for (int i = 0; i < samp_per_event; ++i)
        {
            yv.push_back( rnd.Rndm() );
        }

        //I want to save "events_per_file" events per one file
        if(file_i % events_per_file == 0) f_tree.Open(s_output_file.c_str(), "RECREATE");

        TTree tree("t1", "Tree with result");

        double just_some_value = file_i;
        tree.Branch("just_some_value", &just_some_value, "just_some_value/D");

        TCanvas canv("c", "c", 0, 0, 1900, 1000);
        tree.Branch("canvas_tr", "TCanvas", &canv);

        TGraph graph_ch1(samp_per_event, &xv[0], &yv[0]);
        graph_ch1.Draw();

        tree.Fill();
        if(file_i % events_per_file == 0) f_tree.Write();
        if(file_i % events_per_file == 0) f_tree.Close();

    }


    cout << "all is ok" << endl;
    return 0;
}

Could you help me?

Thank you in advance.
Best regards, Vladislav.

Why do you want to have one tree for each event? Put everything in the same tree. Call Fill once per event.

The following version of your program does not produce the warning.

#include <iostream>
#include <string>
#include <iomanip>


#include "TGraph.h"
#include "TFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "TRandom.h"

using namespace std;

void vla()
{

    TFile *f_tree;

    string s_output_file = "/home/darkside/Vlad_Programs/test.root";
    const int events_per_file = 2;
    const int n_events = 2;
    const int samp_per_event = 100;

    vector<double> xv;
    for (int i = 0; i < samp_per_event; ++i)
    {
        xv.push_back(i);
    }

    TRandom rnd;


    for(int file_i = 0; file_i < n_events; file_i++)
    {
        vector<double> yv;
        for (int i = 0; i < samp_per_event; ++i)
        {
            yv.push_back( rnd.Rndm() );
        }

        //I want to save "events_per_file" events per one file
        if(file_i % events_per_file == 0) {
              f_tree = new TFile(s_output_file.c_str(), "RECREATE");
         }

        TTree tree("t1", "Tree with result");

        double just_some_value = file_i;
        tree.Branch("just_some_value", &just_some_value, "just_some_value/D");

        TCanvas canv("c", "c", 0, 0, 1900, 1000);
        tree.Branch("canvas_tr", "TCanvas", &canv);

        TGraph graph_ch1(samp_per_event, &xv[0], &yv[0]);
        graph_ch1.Draw();

        tree.Fill();
        if(file_i % events_per_file == 0) f_tree->Write();
        if(file_i % events_per_file == 0) f_tree->Close();

    }
}

Anyway, here a modified version of your code:

#include <iostream>
#include <string>
#include <iomanip>


#include "TGraph.h"
#include "TFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "TRandom.h"

using namespace std;

int test()
{
    

    string s_output_file = "test.root";
    const int events_per_file = 2;
    const int n_events = 2;
    const int samp_per_event = 100;

    vector<double> xv;
    for (int i = 0; i < samp_per_event; ++i)
    {
        xv.push_back(i);
    }

    TRandom rnd;

	
	TFile* f_tree = NULL;
	TTree* tree = NULL;
	
    for(int file_i = 0; file_i < n_events; file_i++)
    {
		double just_some_value = file_i;
		vector<double> yv;
        for (int i = 0; i < samp_per_event; ++i)
        {
            yv.push_back( rnd.Rndm() );
        }
		TCanvas canv("c", "c", 0, 0, 1900, 1000);
		TGraph graph_ch1(samp_per_event, &xv[0], &yv[0]);
        graph_ch1.Draw();

		if(file_i % events_per_file == 0) 
		{
			f_tree = TFile::Open(s_output_file.c_str(), "RECREATE");
			tree = new TTree("t1", "Tree with result");
			tree->Branch("just_some_value", &just_some_value, "just_some_value/D");
			tree->Branch("canvas_tr", "TCanvas", &canv);
		}
        
        
        //I want to save "events_per_file" events per one file        
        tree->Fill();
        
        if(file_i % events_per_file == events_per_file-1) 
		{
			f_tree->Write();
			f_tree->Close();
			delete f_tree;
			f_tree = NULL;
			tree = NULL;
		}
    }

	if(f_tree)
	{
		f_tree->Write();
		f_tree->Close();
		delete f_tree;
		f_tree = NULL;
		tree = NULL;
	}

    cout << "all is ok" << endl;
    return 0;
}

I am not specialist in root trees. May be your variant is better.

In any case, how to save root tree?

As I understand your variant is to put TTree tree("t1", "Tree with result"); outside the loop.
This code (one tree with per file) has the same error:

#include <iostream>
#include <string>
#include <iomanip>


#include "TGraph.h"
#include "TFile.h"
#include "TRandom.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "TRandom.h"

using namespace std;

int main(int argc, char *argv[])
{
    TFile f_tree;
    TTree tree("t1", "Tree with result");


    string s_output_file = "/home/darkside/Vlad_Programs/test.root";
    const int events_per_file = 2;
    const int n_events = 2;
    const int samp_per_event = 100;

    vector<double> xv;
    for (int i = 0; i < samp_per_event; ++i)
    {
        xv.push_back(i);
    }

    TRandom rnd;


    for(int file_i = 0; file_i < n_events; file_i++)
    {
        vector<double> yv;
        for (int i = 0; i < samp_per_event; ++i)
        {
            yv.push_back( rnd.Rndm() );
        }

        //I want to save "events_per_file" events per one file
        if(file_i % events_per_file == 0) f_tree.Open(s_output_file.c_str(), "RECREATE");



        double just_some_value = file_i;
        tree.Branch("just_some_value", &just_some_value, "just_some_value/D");

        TCanvas canv("c", "c", 0, 0, 1900, 1000);
        tree.Branch("canvas_tr", "TCanvas", &canv);

        TGraph graph_ch1(samp_per_event, &xv[0], &yv[0]);
        graph_ch1.Draw();

        tree.Fill();
        if(file_i % events_per_file == 0) f_tree.Write();
        if(file_i % events_per_file == 0) f_tree.Close();

    }


    cout << "all is ok" << endl;
    return 0;
}

The version I posted does not have the error

Many thanks!
When I was writing my post you sent the answer.

Dear ferhue, many thanks for your help!
I had also several errors in my code, but you fixed them.

1 Like