Help with writing multidimensional array to a tree

Hi All,

I need help with writing the multidimensional arrays into the ttree branches. I have a structure.

struct pixel_info{
int row;
int column;
int n_range;
bool range[2];
int n_vcal;
int n_tests;
int vcal[2][400];
float ADC[2][400][60];
};

I managed to create a branch for each pixel, but can not find a way to write the arrays in. CINT does not give me any errors but when I look at the results they do not make sense.

I am using the following code to create the branch:

tree->Branch(pixel_row_column, &pixel.row,“pixel.row/I:pixel.column/I:pixel.n_range/I:pixel.range[pixel.n_range]/I:pixel.n_vcal/I:pixel.vcal[pixel.n_range][pixel.n_vcal]/I:pixel.n_tests/I:pixel.ADC[pixel.n_range][pixel.n_vcal][pixel.n_tests]/F” );

Please let me know if I am doing something wrong or direct me to a working example.

Thank you very much,

Dmitry.

Hi,

You can only have use one variable dimension when using the leaflist branch creation method. (In part because the list can not know the real size of the inner dimension and thus can not possibly find the elements).

In order to use a more complex structure you will need to either use vector of vector (of vectors) (and need to generate the dictionary for them) or use a compiled class.

Cheers,
Philippe.

Thank you Philippe! I am trying to make a compiled class but running into problems there as well (see my new post on build problems) I will try the nested vector solution, it seems the simplest.

Cheers,

Dmitry.

Hi Dmitry,

You can easily generated shared library with dictionary without using a makefile. Simply use ACLiC:.L myscript.C+

Cheers,
Philippe.

I am now using a compiled class, but still not able to get sub-branches for the multidimensional arrays. Instead I get the leaves like: ADC[2][400][60]. How do I set it up so it makes sub branches?

Right now I am using:

where “pixel” is my class:

[code]#ifndef ROOT_Pixel_Info
#define ROOT_Pixel_Info

//////////////////////////////////////////////////////////////////////////
// //
// Pixel //
// //
// Description of the pixel info parameters //
// //
//////////////////////////////////////////////////////////////////////////

#include “TObject.h”
#include “TClonesArray.h”
#include “TRefArray.h”
#include “TRef.h”
#include “TH1.h”
#include “TBits.h”
#include “TMath.h”

//structure to hold pixel info
class Pixel_Info : public TObject {
private:
int row;
int column;
int n_range;
int range[2];
int n_vcal;
int n_tests;
int vcal[2][400];
float ADC[2][400][60];
public:
Pixel_Info() { row = 0; column = 0; n_range = 0; n_vcal=0; n_tests=0; }
virtual ~Pixel_Info() {}

 void Print() const;

 //getter
 int get_row() {return row;}
 int get_column() {return column;}
 int get_n_range() {return n_range;}
 int get_range(int i) {return range[i];}
 int get_n_vcal() {return n_vcal;}
 int get_n_tests() {return n_tests;}
 int get_vcal(int i, int j) {return vcal[i][j];}
 float get_ADC(int i, int j, int k) {return ADC[i][j][k];}
 //setters
 void set_row(int i) {row = i;}
 void set_column(int i) {column = i;}
 void set_n_range(int i) {n_range = i;}
 void set_range(int i, int j) {range[i] = j;}
 void set_n_vcal(int i) {n_vcal = i;}
 void set_n_tests(int i) {n_tests = i;}
 void set_vcal(int i, int j, int x) {vcal[i][j] = x;}
 void set_ADC(int i, int j, int k, float x) {ADC[i][j][k] = x;}
 ClassDef(Pixel_Info,1);

};
#endif
[/code]

Thank you,

Dmitry.

[quote]I am now using a compiled class, but still not able to get sub-branches for the multidimensional arrays. Instead I get the leaves like: ADC[2][400][60].[/quote] This is the expected behavior.

[quote]How do I set it up so it makes sub branches?[/quote]I am not sure ‘how’ you want to split? What is your goal?

Cheers,
Philippe.

Here is my problem in a nutshell. I have text with file with calibration data for 1000 pixels=P, which I want to transform into root tree for easier analysis.

For each P there are 2 X values, for each X there are about 100 Y values, for each Y value there are about 40 Z values.

So, I thought that would be nice to have a branch for each P, that splits into 2 X branches, which splits into 100 Y leaves containing arrays of Z values.

Also I would for each P branch like to have 2 X leaves containing arrays of Y values and each tree would have P leaves containing arrays of X values.

I have tried writing a class with nested vectors:

[code] class Pixel_Info_v2 : public TObject {
private:
//row and column indexes branches of the tree
int row;
int column;

 //container of range values and other containers of containers indexed by number of ranges
 int n_range;
 int n_vcal;
 int n_tests;
 std::vector<int> v_range;
 std::vector<std::vector<int> > v2_vcal;
 std::vector<std::vector<std::vector<float> > > v3_ADC;

public:
//some methods
[/code]

But all I still did not get what I want. I willing to try any ideas.

Thank you,

Dmitry.[/code]

[quote]Also I would for each P branch like to have 2 X leaves containing arrays of Y values and each tree would have P leaves containing arrays of X values. [/quote]This is clear. However, the idea I might come up to actual do that render many potential useful things (like plotting the X for all Y and P vs Y) harder. So my question is ‘for what purpose’ do you want to make those branches? In other word, how do you plan on using them? Using which ‘tools’?

Cheers,
Philippe.

My first task is to analyze Z distributions for each Y (I either have to fit each Z distribution or just simply find average) then plot Y values versus values found from the analysis of Z (i.e. Z average) and fit that distribution for each X and each P.

Eventually, I can get rid of X, because supposedly Y(X2)=k1*Y(X1)+k2, but I want to confirm that by looking at values I get from Z analysis, that is why it is better to keep Y(X1) and Y(X2) separate in the beginning.

Other potentially interesting thing to plot in the future is Z values vs P for certain Y(X1) or Y(X2).

I can not think of anything else at the moment.

Cheers,

Dmitry.

Hi,

I would simply use the following:[code]
class Pixel_Info : public TObject {

 float ADC_1[400][60]; 
 float ADC_2[400][60]; 

};[/code]This because the X1 and X2 values could/should be readable separately (since you will eventually drop one of the two).
I would not separate any further since your analysis involves a lot of (loop over all Ys or Ps). Separating those in separate branches would make the looping much harder (and not supported by the default tools (TTree::Draw in particular).

Cheers,
Philippe.