Multi-Dimensional TTree

Greetings,

I seem to be having an issue with saving multi-dimensional branches in a TTree.
Here is a clip of my code.

  
void gamma_Trial_III(){

  const Int_t len = 10;

  TChain *chain = new TChain("Lep");

 CLIPPED Branch Setting due to this not related to problem
   
  TTree *t4 = new TTree("Lep_Tree","Lep_Tree");


  
  Int_t photon_num;

  Float_t mm_PEpEmGam[len][len], mm_EpEmGam[len][len], mE_PEpEmGam[len][len];
  t4->Branch("photon_num",&photon_num,"photon_num/I");	

  Int_t Ngam;  
  t4->Branch("Ngam",&Ngam,"Ngam/I");
  	
  t4->Branch("mm_EpEmGam",&mm_EpEmGam,"mm_EpEmGam[photon_num][Ngam]/F");
  t4->Branch("mm_PEpEmGam",&mm_PEpEmGam,"mm_PEpEmGam[photon_num][Ngam]/F");
  t4->Branch("mE_PEpEmGam",&mE_PEpEmGam,"mE_PEpEmGam[photon_num][Ngam]/F");


CLIPPED constant variable initialzation


//----------------Initializing Lorentz Vectors -------------------------------------
		
  TLorentzVector vT, vEg, vP, vEp, vEm, vGamma, vGamma1, vGamma_cor;  //vGamma1 used for invariatnt mass with gamma
  vT.SetPxPyPzE(0.0, 0.0, 0.0, M_P);
      
  for( Int_t i = 0; i < nEvent; i++){  //nEvent
    chain->GetEntry(i); 
	
	if(photon_number==0){continue;} 

//-------------------momenta squared-----------------------------------	
	Double_t p2_P = P_Px*P_Px + P_Py*P_Py + P_Pz*P_Pz;
	Double_t p2_Ep = Ep_Px*Ep_Px + Ep_Py*Ep_Py + Ep_Pz*Ep_Pz;
	Double_t p2_Em = Em_Px*Em_Px + Em_Py*Em_Py + Em_Pz*Em_Pz;
		
//---------------------------Energy -----------------------------------	
	Double_t E_P = sqrt(p2_P + M_P*M_P);
	Double_t E_Ep = sqrt(p2_Ep + Melectron*Melectron);
	Double_t E_Em = sqrt(p2_Em + Melectron*Melectron);	


//----------------setting Lorentz Vectors -------------------------------------
		 
	vP.SetPxPyPzE(P_Px, P_Py, P_Pz, E_P);
	vEp.SetPxPyPzE(Ep_Px, Ep_Py, Ep_Pz, E_Ep);
	vEm.SetPxPyPzE(Em_Px, Em_Py, Em_Pz, E_Em);

	TLorentzVector IV_EpEmVec = (vEp + vEm);  	   	  
	TLorentzVector IV_PEpEmVec = (vP + vEp + vEm);  	   	  
			
	for (Int_t j = 0; j<photon_number; j++){	

	  vEg.SetPxPyPzE(0.0, 0.0, IN_photon_E[j], IN_photon_E[j]);

	  for (Int_t q = 0; q<Ngam; q++){

//----------------setting Outgoing Gamma Lorentz Vector -------------------------------------

		vGamma.SetPxPyPzE(Phot_Px[q], Phot_Py[q], Phot_Pz[q], Phot_P[q]);		  
		  
//----------------------------------------missing mass vectors w/Outgoing Gamma ----------------------------------------------------------------
           
		TLorentzVector MM_EpEmGamVec = (vEg + vT) - (vEp + vEm + vGamma); 			
		TLorentzVector MM_PEpEmGamVec = (vEg + vT) - (vP + vEp + vEm + vGamma);
			
		TLorentzVector MM_PEmGamVec = (vEg + vT) - (vP + vEm + vGamma); 			
				
		mm_EpEmGam[j][q] = MM_EpEmGamVec.M(); 
		mm_PEpEmGam[j][q] = MM_PEpEmGamVec.M();		
		mE_PEpEmGam[j][q]  = MM_PEpEmGamVec.E(); 
								
	  } // Closes loop of outgoing gamma			 		 		
				

	}  //closes loop of incoming gamma
	
	  	
	t4->Fill();

  }

  t4->Write();
  f.Close();
}	
  

The full program will run, but it fills the branches with 0.
However if I ask to std::cout<<mE_PEpEmGam[j][q] <<endl; during the running of the program, it screen outputs reasonable numbers, but never fills the branch with these numbers.

Help please.

Thanks
Michael

Hi Michael,

You need to initialize the length variable before using them in the list of leaves.

Cheers,
Philippe.

The length of the array varies according the the two parameters photon_num and Ngam.
For a one-dimensional array, initializing this way works, why does it not work for mult-dimensional?

Michael

Hi,

[quote]For a one-dimensional array, initializing this way works, why does it not work for mult-dimensional?
[/quote]After double checking, the leaflist technique (that you used) still does not support arrays with 2 variable dimensions (but obviously does not complain eventhough it should).

To handle this case we recommend using a vector<vector >.

Cheers,
Philippe.

Hi again, I think error is relevant to this thread still

I try the method of vector<vector> below is a trial code

#include "TROOT.h"
#include "TRint.h"
#include "TH1F.h"
#include "TCanvas.h"
#include "TChain.h"

#include "TVector3.h"
#include "TMath.h"
#include "TFile.h"
#include "TSystem.h"
#include "TGStatusBar.h"
#include "TSystem.h"
#include "TXMLEngine.h"
#include "TTree.h"
#include "TLorentzVector.h"
#include "TNtuple.h" 
#include <cstdlib>
#include<string> 
#include<iostream> 
#include<fstream>
#include<iomanip>
#include<cmath>
#include<vector>


#ifdef __MAKECINT__
#pragma link C++ class vector<float>+;
#pragma link C++ class vector<vector<float>>+;
#endif

void Trial(){

//gROOT->ProcessLine("#include <vector>");

    TFile f("/Volumes/Mac_Storage/Work_Data/g_timed_Dalitz_t15.root","recreate");

    TTree *Try = new TTree("Try","Try");


	std::vector<vector<float>>* vpx;
	std::vector<vector<float>>* vpy;
	std::vector<float>* vpx_one;
	std::vector<float>* vpy_one;

	Try->Branch("vpx", &vpx);
	Try->Branch("vpy", &vpy);

	for(int i =0; i<100; i++){
	    vpx->clear();
		vpy->clear();
		vpx_one->clear();
		vpy_one->clear();						

		for(int j =0; j<10; j++){
			vpx_one->push_back(i);
			vpy_one->push_back(i);
			vpx->push_back(vpx_one);
			vpy->push_back(vpy_one);
		}

	    Try->Fill();
	}

    Try->Write();
	f.Close();

}

And I receive this error

Error in TTree::Branch: The class requested (vector<vector<float,allocator > >) for the branch “vpx” refer to an stl collection and do not have a compiled CollectionProxy. Please generate the dictionary for this class (vector<vector<float,allocator > >)
Error in TTree::Branch: The class requested (vector<vector<float,allocator > >) for the branch “vpy” refer to an stl collection and do not have a compiled CollectionProxy. Please generate the dictionary for this class (vector<vector<float,allocator > >)
Error: illegal pointer to class object vpx_one 0x0 3243 test.C:51:
*** Interpreter error recovered ***

Thanks Again

Michael

Hi,

Yes, it seems that the dictionary for vector<vector > has not been created. You could do so by compiling your script (since you arlready have the #pragma in it) with ACLiC or calling:gInterpreter->GenerateDictionary("vector<vector<float> >","vector");

Cheers,
Philippe.

Thanks again,

Unfortunately that still doesn’t work.

When I add line:

I still receive same error, and I do know know what ACLiC means (google doesn’t either :slight_smile: ).
Question is how to fix and why was the dictionary not created in the first place?

BR
Michael

Hi,

[quote]google doesn’t either [/quote]Add the work ‘ROOT’ and you will find it :slight_smile:. Also see the User’s Guide chapter “CINT the C++ Interpreter”.

ACLiC is the automatic compiler and linker for Cint and can be trivial involved from CINT by simple adding a trailing + at the end of the script loading invocation. For example:.L myscript.C+

[quote]I still receive same error[/quote]That is very surprising. Which version of ROOT are you using? Did GenerateDictionary generate any output? What is the result of:[code]root [0] gInterpreter->GenerateDictionary(“vector<vector >”,“vector”);
root [1] .class vector<vector >

class vector<vector<float,allocator >,allocator<vector<float,allocator > > >
size=0x18 FILE:/local2/pcanal/root_working/code/root.untouched/AutoDict_vector_vector_float____cxx.so LINE:-1[/code]

Cheers,
Philippe.

Well I feel somewhat foolish, I actually always execute my scripts like .L myscript.C+ in ROOT.

I use version 5.26/00 as I cannot upgrade higher due to gcc limitations.

When I execute:

root [0] gInterpreter->GenerateDictionary("vector<vector<float> >","vector");
Error: Can't call TCint::GenerateDictionary("vector<vector<float> >","vector") in current scope (tmpfile):1:
Possible candidates are...
*** Interpreter error recovered ***

BR
Michael

Hi Michael,

GenerateDictionary was introduced in v5.28. In v5.26, you still need to manually request the dictionary which you seemed to have done. Instead of #pragma link C++ class vector<vector<float>>+;try#pragma link C++ class vector<vector<float> >+;(i.e. with the extra space.

Cheers,
Philippe.

Hi Philippe,

When I add the extra space and execute as

root -l Trial.C

I get this error

Processing Trial.C...
Error in <TTree::Branch>: The class requested (vector<vector<float,allocator<float> > >) for the branch "vpx" refer to an stl collection and do not have a compiled CollectionProxy.  Please generate the dictionary for this class (vector<vector<float,allocator<float> > >)
Error in <TTree::Branch>: The class requested (vector<vector<float,allocator<float> > >) for the branch "vpy" refer to an stl collection and do not have a compiled CollectionProxy.  Please generate the dictionary for this class (vector<vector<float,allocator<float> > >)
Error: illegal pointer to class object vpx_one 0x0 3243  Trial.C:53:
*** Interpreter error recovered ***

If I execute as ACLiC

root -l Trial.C+

I receive an error similar

Processing Trial.C+...
Info in <TUnixSystem::ACLiC>: creating shared library /Volumes/Mac_Storage/Work_Codes/Dalitz_Codes/VECTOR_TEST/./Trial_C.so
Note: Link requested for already precompiled class vector<float,allocator<float> > (ignore this message) :0:
/Volumes/Mac_Storage/Work_Codes/Dalitz_Codes/VECTOR_TEST/./Trial.C: In function 'void Trial()':
/Volumes/Mac_Storage/Work_Codes/Dalitz_Codes/VECTOR_TEST/./Trial.C:59: error: no matching function for call to 'std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::push_back(std::vector<float, std::allocator<float> >*&)'
/usr/include/c++/4.0.0/bits/stl_vector.h:602: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::vector<float, std::allocator<float> >, _Alloc = std::allocator<std::vector<float, std::allocator<float> > >]
/Volumes/Mac_Storage/Work_Codes/Dalitz_Codes/VECTOR_TEST/./Trial.C:60: error: no matching function for call to 'std::vector<std::vector<float, std::allocator<float> >, std::allocator<std::vector<float, std::allocator<float> > > >::push_back(std::vector<float, std::allocator<float> >*&)'
/usr/include/c++/4.0.0/bits/stl_vector.h:602: note: candidates are: void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::vector<float, std::allocator<float> >, _Alloc = std::allocator<std::vector<float, std::allocator<float> > >]
i686-apple-darwin9-g++-4.0.1: /Volumes/Mac_Storage/Work_Codes/Dalitz_Codes/VECTOR_TEST/./Trial_C_ACLiC_dict.o: No such file or directory
Error in <ACLiC>: Compilation failed!
Error: Function Trial() is not defined in current scope  :0:
*** Interpreter error recovered ***

BR
Michael

Hi Michael,

There is a C++ syntax error in your code. It looks like you are trying to a push_back a pointer to vector into the vector<vector > (on line 59).

Cheers,
Philippe.

Philippe,

I caught that mistake right before you posted, however in correcting the mistake

#include "TROOT.h"
#include "TRint.h"
#include "TH1F.h"
#include "TCanvas.h"
#include "TChain.h"

#include "TVector3.h"
#include "TMath.h"
#include "TFile.h"
#include "TSystem.h"
#include "TGStatusBar.h"
#include "TSystem.h"
#include "TXMLEngine.h"
#include "TTree.h"
#include "TLorentzVector.h"
#include "TNtuple.h" 
#include <cstdlib>
#include<string> 
#include<iostream> 
#include<fstream>
#include<iomanip>
#include<cmath>
#include<vector>


#ifdef __MAKECINT__
#pragma link C++ class vector<float>+;
#pragma link C++ class vector<vector<float> >+;
#endif

void Trial(){


    //gROOT->ProcessLine("#include <vector>");


    TFile f("/Volumes/Mac_Storage/Work_Data/g_timed_Dalitz_t15.root","recreate");

    TTree *Try = new TTree("Try","Try");


	std::vector<vector<float> >* vpx;
	std::vector<vector<float> >* vpy;
	std::vector<float> vpx_one;
	std::vector<float> vpy_one;

	Try->Branch("vpx", &vpx);
	Try->Branch("vpy", &vpy);

	for(int i =0; i<100; i++){
	    vpx->clear();
		vpy->clear();
		vpx_one.clear();
		vpy_one.clear();						

		for(int j =0; j<10; j++){
			vpx_one.push_back(i);
			vpy_one.push_back(i);
			vpx->push_back(vpx_one);
			vpy->push_back(vpy_one);
		}

	    Try->Fill();
	}

    Try->Write();
	f.Close();

}

I execute using ACLiC I get


 *** Break *** bus error

Not using ACLiC I get same error

Processing Trial.C...
Error in <TTree::Branch>: The class requested (vector<vector<float,allocator<float> > >) for the branch "vpx" refer to an stl collection and do not have a compiled CollectionProxy.  Please generate the dictionary for this class (vector<vector<float,allocator<float> > >)
Error in <TTree::Branch>: The class requested (vector<vector<float,allocator<float> > >) for the branch "vpy" refer to an stl collection and do not have a compiled CollectionProxy.  Please generate the dictionary for this class (vector<vector<float,allocator<float> > >)

BR
Michael

Hi Michael,

You need to initialize pointers:std::vector<vector<float> >* vpx = 0; std::vector<vector<float> >* vpy = 0;

Cheers,
Philippe.

Thank you Philippe,

I did not need to initialize them, all I had to do was upgrade my OS, gcc and install root v.30 and everything compiled correctly.
It didnt solve my initial problem, but at least I got on the correct path.

Thanks again

Michael

Hi,

[quote]I did not need to initialize them[/quote]Humm … you really do. In C++, pointer should always be initialized before being used. In the case: std::vector<vector<float> >* vpx; Try->Branch("vpx", &vpx);TTree::Branch will look at and use the value of ‘vpx’ … when not initialize the value of vpx is random (and could be a valid value like zero) resulting in undetermined result.

Cheers,
Philippe.