Can't read a tree branch with leaves of varied length array

Hello, ROOTers:

I have a root file pi0.FmsEmJet.root (414.1 KB)
and I need to read it. The tree in the root file has branches with multiple leaves, and some of the leaves are array of varied size.

******************************************************************************
*Tree    :FmsEmJet  : Fms Em Jet                                             *
*Entries :     3594 : Total =          949844 bytes  File  Size =     419197 *
*        :          : Tree compression factor =   2.27                       *
******************************************************************************
*Br    0 :hit       : nHits/I:detId[nHits]/I:ch[nHits]/I:e[nHits]/F          *
*Entries :     3594 : Total  Size=     719647 bytes  File Size  =     250772 *
*Baskets :       23 : Basket Size=      32000 bytes  Compression=   2.87     *
*............................................................................*
*Br    1 :clu       : nClus/I:e[nClus]/F:x[nClus]/F:y[nClus]/F               *
*Entries :     3594 : Total  Size=     113834 bytes  File Size  =      76164 *
*Baskets :        4 : Basket Size=      32000 bytes  Compression=   1.48     *
*............................................................................*
*Br    2 :point     : nPoints/I:e[nPoints]/F:x[nPoints]/F:y[nPoints]/F       *
*Entries :     3594 : Total  Size=     115974 bytes  File Size  =      91104 *
*Baskets :        5 : Basket Size=      32000 bytes  Compression=   1.26     *
*............................................................................*

I read the branch by constructing corresponding struct for each branch.
test.C (1.2 KB)

struct hit_t {
    int n;
    int detId[256];
    int ch[256];
    float e[256];
};

struct cluster_t {
    int n;
    float e[16];
    float x[16];
    float y[16];
};

struct point_t {
    int n;
    float e[16];
    float x[16];
    float y[16];
};

void test(const char*fname = "pi0.FmsEmJet.root")
{
    TFile *fin = new TFile(fname, "read");
    TTree *tin = (TTree*) fin->Get("FmsEmJet");
    struct hit_t hit;
    struct cluster_t clu;
    struct point_t point;
    tin->SetBranchAddress("hit", &hit);
    tin->SetBranchAddress("clu", &clu);
    tin->SetBranchAddress("point", &point);

    // const int nEntries = tin->GetEntries();
    const int nEntries = 1;
    for (int ei=0; ei<nEntries; ei++)
    {
	tin->GetEntry(ei);
	cout << "hit\t" << hit.n << "\t";
	for (int hi=0; hi<hit.n; hi++)
	    cout << hit.e[hi] << "\t";
	cout << endl;

	cout << "clu\t" << clu.n << "\t";
	for (int ci=0; ci<clu.n; ci++)
	    cout << clu.e[ci] << "\t" << clu.x[ci] << "\t" << clu.y[ci];
	cout << endl;

	cout << "point\t" << point.n << "\t";
	for (int pi=0; pi<point.n; pi++)
	    cout << point.e[pi] << "\t" << point.x[pi] << "\t" << point.y[pi];
	cout << endl;
    }

    fin->Close();
}

Unfortunately, the readout value is nonsense (except the size value). I don’t know why (I am sure that the array in each struct is large enough). Can anyone help? Thanks in advance.


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.28.06
Platform: Ubuntu 22.04
Compiler: Not Provided


Try with

struct hit_t {
    int n = 256;
    int detId[256];
    int ch[256];
    float e[256];
};

struct cluster_t {
    int n = 16;
    float e[16];
    float x[16];
    float y[16];
};

struct point_t {
    int n = 16;
    float e[16];
    float x[16];
    float y[16];
}

No, I got the same result.

Any new thoughts?

with your initial code I get:

hit	2	4.5765e-41	4.92502e-25	
clu	1	7.5	1.4013e-45	4.59051e-41
point	1	43.9833	3.44383e-41	4.59051e-41

with @pcanal suggestion I get:

hit	2	0	1.21605e-37	
clu	1	7.5	4.59051e-41	4.59051e-41
point	1	43.9833	1.4013e-45	4.59051e-41

so it is not the same result.

@couet

root pi0.FmsEmJet.root -e 'FmsEmJet->Scan("*", "", "", 1);' -q

@Wile_E_Coyote , Yes you are right, the file is tree is quite empty, and sometimes undefined…
I did not check. Thanks.

% root pi0.FmsEmJet.root -e 'FmsEmJet->Scan("*", "", "", 1);' -q
***********************************************************************************************************************************************************************
*    Row   * Instance * hit.hit.n * hit.hit.d * hit.hit.c * hit.hit.e * clu.clu.n * clu.clu.e * clu.clu.x * clu.clu.y * point.poi * point.poi * point.poi * point.poi *
***********************************************************************************************************************************************************************
*        0 *        0 *         2 *         8 *         8 * 1.7510000 *         1 * 1.9390000 *       0.5 *       7.5 *         1 * 1.9390000 * 2.8681945 * 43.983348 *
*        0 *        1 *         2 *         8 *         8 * 0.1879999 *         1 *           *           *           *         1 *           *           *           *
***********************************************************************************************************************************************************************

I mean both readouts are not what I expected. You can easily check out the energy or position by ‘FmsEmJet->Show(0)’.

The tree is not undefined. It shows so because it has leaves which are arrays of varied length.

I see:

======> EVENT:0
 nHits           = 2
 detId           = 8, 
                  8
 ch              = 8, 
                  8
 e               = 1.751, 
                  0.188
 nClus           = 1
 e               = 1.939
 x               = 0.5
 y               = 7.5
 nPoints         = 1
 e               = 1.939
 x               = 2.86819
 y               = 43.9833
root [2] FmsEmJet->Scan("*", "", "", 1)
***********************************************************************************************************************************************************************
*    Row   * Instance * hit.hit.n * hit.hit.d * hit.hit.c * hit.hit.e * clu.clu.n * clu.clu.e * clu.clu.x * clu.clu.y * point.poi * point.poi * point.poi * point.poi *
***********************************************************************************************************************************************************************
*        0 *        0 *         2 *         8 *         8 * 1.7510000 *         1 * 1.9390000 *       0.5 *       7.5 *         1 * 1.9390000 * 2.8681945 * 43.983348 *
*        0 *        1 *         2 *         8 *         8 * 0.1879999 *         1 *           *           *           *         1 *           *           *           *
***********************************************************************************************************************************************************************

How are the result of Show or Scan not what you expect?

The cluster energy is 1.939, x and y being 0.5 and 7.5. Obviously not what I got when using the “TTree::SetBranchAddress” method.

Indeed. TTree::SetBranchAddress is having difficulty with this tree structure. You can solve the problem by adding a series of call like the following for each and every arrays before the call to TTree::SetBranchAddress

tin->GetLeaf("clu.e")->SetOffset( sizeof(int) );
tin->GetLeaf("clu.x")->SetOffset( sizeof(int) + sizeof(float)*16 ); 
tin->GetLeaf("clu.y")->SetOffset( sizeof(int) + sizeof(float)*16*2 );
// alternatively:  
// tin->GetLeaf("clu.x")->SetOffset(  ((char*)(&(clu.x[0])))-((char*)(&clu)) );
// tin->GetLeaf("clu.y")->SetOffset(  ((char*)(&(clu.y[0])))-((char*)(&clu)) );

[correction to use the TTree variable name used in the original example]

@pcanal Same problem here: “*Break* segmentation violation and failed to access leaf in array from tree contains CORSIKA data
The solution was to use TBranch::GetLeaf” + “TLeaf::SetAddress.

Yes, this will also work.

It works, thank you very much.

I am also curious why the SetBranchAddress method with a struct doesn’t work.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.