How to save TGraphErrors in a tree?

Hello!

I want to save TGraphErrors in the tree, but my method don’t work.

First of all, I explain you what I want.
I want to make fit of TGraphErrors object and save TGraphErrors (object) and fit parameters (double) in the tree.

  1. I know how to save TGraphErrors objects only:
TMultiGraph *mg = new TMultiGraph();
TGraphErrors *gr = new TGraphErrors(xv.size(), &xv[0], &yv[0], &xverr[0], &yverr[0]);
mg->Add(gr);
...
TObjArray Hlist(0);
Hlist.Add(mg);
  1. I know how to save double values only:
TNtuple ntuple("ntuple", "fit results", "x0:y0:chi2");
...
ntuple.Fill(x0, y0, chi2);
TFile f_ntuple(string_ntuple.c_str(), "RECREATE");
ntuple.Write();
f_ntuple.Close();

I have tried the next code in order to save both: graph and doubles:

void CreateTree()
{
	TFile f("D:\\Data_work\\tree.root","recreate");
	TTree t1("t1","a simple Tree with simple variables");
	
	Double_t x0, y0, amp;
	
	//create vectors
	vector<double> xv;
	vector<double> yv;
	vector<double> xverr;
	vector<double> yverr;
	
	//loop to create several graphs
	for(int j = 0; j < 10; j++)
	{	
		//fill vectors		
		for (Int_t i= -10; i<= 10; i++) 
		{
			xv.push_back(i);
			yv.push_back(0.2 * i*i + gRandom->Gaus(0, 1));
			xverr.push_back(0);
			yverr.push_back(1);
		}
		
		TGraphErrors *gr = new TGraphErrors(xv.size(), &xv[0], &yv[0], &xverr[0], &yverr[0]);
		gr->SetMarkerColor(4);
		gr->SetMarkerStyle(kFullCircle);
		
		TF1 *fitFcn = new TF1("fitFcn", fitFunction, -10, 10, 3);
		gr->Fit("fitFcn", "R");
		
		x0 = fitFcn->GetParameter(2);
		y0 = fitFcn->GetParameter(1);
		amp = fitFcn->GetParameter(0);
		
		//cout << "x0 = " << x0 << " y0 = " << y0 << " amp = " << amp << endl;
		//gr->Draw("AP");
		
		t1.Branch("x0",&x0,"x0/D");
		t1.Branch("y0",&y0,"y0/D");
		t1.Branch("amp",&amp,"amp/D");
		t1.Branch("gr","TGraphErrors",&gr, 128000, 0);
		
		t1.Fill();
		
		xv.clear();
		yv.clear();
		xverr.clear();
		yverr.clear();
	}
	
	
	t1.Write();
}

But the result is differs from my expectation: I can’t open graph object like 1) method.

  1. prntscr.com/8vgg9f (via TObjArray); picture just for example
  2. prntscr.com/8vggw1 (via TNtuple )
  3. my attempt (via TTree) prntscr.com/8vghs2

I expected to find in the tree the array of these graphs prntscr.com/8vgisx

Thanks for advance.

Hi,

to write a tree containing per entry a TGraphErrors and the values of the parameters of a linear function, a starting point which you could adapt to your case is:

/// Just to make all graphs different from each other
void fillRandomAndFit(TGraphErrors& g){
   for (int i = 0;i<10;++i){ 
      g.SetPoint(i, i + gRandom->Uniform(-.5,.5), gRandom->Uniform(-.5,.5));
   }
   g.Fit("fitFunc", "N");
}

void treeOfTGraphs() {

	TGraphErrors g(10);
	TF1 fitFunc("fitFunc","[0]+[1]*x",0,10);
        double m,q;
      
	TFile ofile("myFile.root","RECREATE");
	TTree tree("treeOfGraphs","TreeOfGraphs");
	tree.Branch("graph",&g);
	tree.Branch("q",&q);
	tree.Branch("m",&m);


    for (int i=0;i<100;++i){
       fillRandomAndFit(g);
       q = fitFunc.GetParameter(0);
       m = fitFunc.GetParameter(1);
       tree.Fill();
    }

    tree.Write();
    ofile.Close();
}

Cheers,
Danilo

Hello!

Thanks for the answer!
But I can’t understand the principial differense between our programms.

Ok, I try to explain in more details my problem.

For example, I have x vs y dependency.
I create TGraphErrors object and fit if.
I will have the vector of parameters pv, chi2 value and TGraphErrors object.
I save all these in the tree.
Then I read the tree and cut a subset:

	TChain *chain = new TChain("ntuple");
	chain->Add("D:\\Data_work\\myFile.root");
	TCut cut = "p1 > 0.2 && chi2 < 1";	

I can Draw the correlation between parameters i and j:

chain->Draw("p1:p2", cut);

I want to Draw several TGraphErrors from this subset.
How to do this?

Thank you in advance.

There is no difference: mine is a skeleton to show the way of achieving what you ask in a general and minimal way.

This is is too much to ask to TTree::Draw :wink:
In this case, you can loop on the entries yourself and draw the graphs for those that pass your selection.

Cheers,
Danilo

Danilo, I am very grateful to you for your help.

I don’t have enough experiense with trees.
Could you give me the simple example how to get graph from the tree and organize the loop?

Thank you in advance.

Hi Vladislav,

no problem.
So, the documentation can be found here: root.cern.ch/root/htmldoc/guide … ding-trees
For your particular case, since you are not using ROOT6 (it did not make it yet on Windows), you can ignore TTreeReader: this class does not exist in ROOT5.
To be more concrete, to read your tree and apply a cut, you need to do:
in python

import ROOT
f = ROOT.TFile("myFile.root")
for e in f.treeOfGraphs:
   if e.q > 0.1: continue
   # Here the work 
raw_input("Press a key to continue.")

in C++

void readTree(){
   TFile f("myFile.root");
   TTree* t;
   f.GetObject("treeOfGraphs",t);
   TGraphErrors* graph = new TGraphErrors();
   double q;
   t->SetBranchAddress("graph",&graph);
   t->SetBranchAddress("q",&q);
   for (int i=0;i<t->GetEntries();++i){
      t->GetEntry(i);
      if (q>.1) continue;
      cout << "q is " << q << endl;
      // do work
      graph->Dump();
   }

}

Cheers,
Danilo

Danilo, your links are very useful.

But I still have two questions. Maybe you can help me.

  1. I did not undestand what this code do:

Does it just print in concole all properties of the object?

  1. I have understood how to realize my desire: I shoud save my graphs into the new .root file.
void readTree()
{
	TObjArray Hlist(0);

	TFile f("D:\\Data_work\\myFile.root");
	TTree* t;
	f.GetObject("treeOfGraphs",t);

	TGraphErrors* graph = new TGraphErrors();
	double q;
	t->SetBranchAddress("graph",&graph);
	t->SetBranchAddress("q",&q);
	  
	for(int i = 1; i < t->GetEntries(); ++i)
	{
		t->GetEntry(i);
		Hlist.Add(graph); 
	}   

	TFile ofile_Hlist("D:\\Data_work\\graphs.root", "RECREATE");
	Hlist.Write();
	ofile_Hlist.Close();   
}

But all graphs in the graphs.root are equal, so there is an error.
Is it right code in the loop?

Hlist.Add(graph); 

Thank you in advance.

  1. This is a place holder to show you that the graphs are properly deserialised
  2. The code was saving N time the last graph read. The solution is
void readTree2()
{
   TObjArray Hlist(0);
   Hlist.SetOwner(kTRUE);

   TFile f("myFile.root");
   TTree* t;
   f.GetObject("treeOfGraphs",t);

   TGraphErrors* graph = new TGraphErrors();
   double q;
   t->SetBranchAddress("graph",&graph);
   t->SetBranchAddress("q",&q);
    
   for(int i = 1; i < t->GetEntries(); ++i)
   {
      t->GetEntry(i);
      Hlist.Add(new TGraphErrors(*graph));
   }   

   TFile ofile_Hlist("graphs.root", "RECREATE");
   Hlist.Write();
   ofile_Hlist.Close();   
}

Danilo, thank you very much!