Branch with TClonesArray containing fixed array

Dear rooters,

I have been trying to generate tree with branch made of TClonesArray.
This TClonesArray are classes that contain array of fixed size as member.
The code I am developing is more complicated but below is a minimal example :

class TCube:public TObject {
  Int_t x[3]; //[3]
  Int_t n ;
public:
  TCube(Int_t a, Int_t b, Int_t c, Int_t i) {
    x[0] = a;
    x[1] = b;
    x[2] = c;
    n = i ;
  } 
  TCube() {
    x[0] = 0;
    x[1] = 0;
    x[2] = 0;
    n = 0 ;
  } 
  Dump() { cout << x[0] << " " << x[1] << " " << x[2]<< endl ;}
  virtual TClass* IsA();
  virtual void ShowMembers(TMemberInspector& insp, char* parent);
  virtual void Streamer(TBuffer& b);
  virtual ~TCube();
  ClassDef(TCube,1)

};

void test_tree(){
 
 TClonesArray *a = new TClonesArray("TCube");
 TClonesArray &aa = *a;

 TFile *f = new TFile("test.root","recreate");
 TTree *t = new TTree("test","test");
 
 t->Branch("branch",&a);

 for(int n = 0;n<10;n++){
   for(int i=0;i<3;i++){
     new(aa[i]) TCube(i,i+10,i+100,i+1000);
   }
   t->Fill();
 }
 f->Write();
 f->Close();
}

Result of test->Print() is, as expected (?) :

******************************************************************************
*Tree    :test      : test                                                   *
*Entries :       10 : Total =            5159 bytes  File  Size =          0 *
*        :          : Tree compression factor =   1.00                       *
******************************************************************************
*Br    0 :branch    : Int_t branch_                                          *
*Entries :       10 : Total  Size=       5289 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    1 :branch.fUniqueID : UInt_t fUniqueID[branch_]                       *
*Entries :       10 : Total  Size=        946 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    2 :branch.fBits : UInt_t fBits[branch_]                               *
*Entries :       10 : Total  Size=        922 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    3 :branch.x[3] : Int_t x[branch_]                                     *
*Entries :       10 : Total  Size=        787 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    4 :branch.n  : Int_t n[branch_]                                       *
*Entries :       10 : Total  Size=        778 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*
*Br    5 :branch.fgIsA : TClass* fgIsA[branch_]                              *
*Entries :       10 : Total  Size=        802 bytes  One basket in memory    *
*Baskets :        0 : Basket Size=      32000 bytes  Compression=   1.00     *
*............................................................................*

Now, if I scan the result (test->Scan(“x:n”)) :

[code]root [1] test->Scan(“x:n”)


  • Row * Instance * x * n *

  •    0 *        0 *        11 *        11 *
    
  •    0 *        1 *        78 *        75 *
    
  •    0 *        2 *        78 *        75 *
    
  •    0 *        3 *        78 *           *
    
  •    0 *        4 *        78 *           *
    
  •    0 *        5 *        78 *           *
    
  •    0 *        6 *        78 *           *
    
  •    0 *        7 *        78 *           *
    
  •    0 *        8 *        78 *           *
    
  •    1 *        0 *        11 *        11 *
    
  •    1 *        1 *        78 *        75 *
    
  •    1 *        2 *        78 *        75 *
    
  •    1 *        3 *        78 *           *
    
  •    1 *        4 *        78 *           *
    
  •    1 *        5 *        78 *           *
    
  •    1 *        6 *        78 *           *
    
  •    1 *        7 *        78 *           *
    
  •    1 *        8 *        78 *           *
    
  •    2 *        0 *        11 *        11 *
    
  •    2 *        1 *        78 *        75 *
    
  •    2 *        2 *        78 *        75 *
    
  •    2 *        3 *        78 *           *
    
  •    2 *        4 *        78 *           *
    
  •    2 *        5 *        78 *           *
    
  •    2 *        6 *        78 *           *
    

Type to continue or q to quit ==> q


[/code]

Albeit the fact that the result here is not what I expect in terms of figures (it works in the code I am presently developing), what concerns me the most is that I would expect x to be some sort of array with two indexes.
And more important that the instance of n is present every 3 instances of x like :

***********************************************
*    Row   * Instance *         x *         n *
***********************************************
*        0 *        0 *        11 *        11 *
*        0 *        1 *        78 *           *
*        0 *        2 *        78 *           *
*        0 *        3 *        78 *        75 *
*        0 *        4 *        78 *           *
*        0 *        5 *        78 *           *
*        0 *        6 *        78 *        75 * 
*        0 *        7 *        78 *           *
*        0 *        8 *        78 *           *
*        1 *        0 *        11 *        11 *
*        1 *        1 *        78 *           *
*        1 *        2 *        78 *           *
*        1 *        3 *        78 *        75 *
*        1 *        4 *        78 *           *
*        1 *        5 *        78 *           *
*        1 *        6 *        78 *        75 *
*        1 *        7 *        78 *           *
*        1 *        8 *        78 *           *

In the code I am developing results even look random.
Is there a way to solve this problem ? I am probably missing something.

Regards
Julien

Hi Julien,

Why add: virtual TClass* IsA(); virtual void ShowMembers(TMemberInspector& insp, char* parent); virtual void Streamer(TBuffer& b); ? … those are already part of ClassDef.

Philippe.

Dear Philippe.

I just copy past an example without really thinking. One of the reason is that I had a error telling me about the
Streamer. So I add both the Streamer and the ClassDef.
I remove the three virtual member you point me at: no change in the behaviour.

Regards
Julien

Hi,

[quote]One of the reason is that I had a error telling me about the
Streamer.[/quote]Most likely you must have been missing the dictionary at that time.

Cheers,
Philippe.

[quote]And more important that the instance of n is present every 3 instances of x like :[/quote]This is the intended behavior (See root.cern.ch/root/html/TTreePlay … layer:Scan):[code]Arrays (within an entry) are printed in their linear forms.
If several arrays with multiple dimensions are printed together,
they will NOT be synchronized. For example print
arr1[4][2] and arr2[2][3] will results in a printing similar to:

  • Row * Instance * arr1 * arr2 *

  •    x *        0 * arr1[0][0]* arr2[0][0]*
    
  •    x *        1 * arr1[0][1]* arr2[0][1]*
    
  •    x *        2 * arr1[1][0]* arr2[0][2]*
    
  •    x *        3 * arr1[1][1]* arr2[1][0]*
    
  •    x *        4 * arr1[2][0]* arr2[1][1]*
    
  •    x *        5 * arr1[2][1]* arr2[1][2]*
    
  •    x *        6 * arr1[3][0]*           *
    
  •    x *        7 * arr1[3][1]*           *[/code](implementing the proper synchronization in all possible cases is a challenging task).
    

[quote]Albeit the fact that the result here is not what I expect in terms of figures

In the code I am developing results even look random. [/quote]Humm … That’s more worrisome. Do you ever see the ‘right’ information when plotting/scan ‘x’ (for example when Scan ‘just’ for x)?

Cheers,
Philippe.

Dear Philippe,

Well, maybe I did not properly expressed myself. When I say “random” I was not talking about the values but the way they appeared in each each column, e.g :

***********************************************
*    Row   * Instance *         x *         n *
***********************************************
*        0 *        0 *        11 *        11 *
*        0 *        1 *        78 *           *
*        0 *        2 *        78 *        75 *
*        0 *        3 *        78 *        75 *
*        0 *        4 *        78 *           *
*        0 *        5 *        78 *           *
*        0 *        6 *        78 *           *
*        0 *        7 *        78 *           *
*        0 *        8 *        78 *           *
*        1 *        0 *        11 *           *
*        1 *        1 *        78 *           *
*        1 *        2 *        78 *        11 *
*        1 *        3 *        78 *           *
*        1 *        4 *        78 *        75 *
*        1 *        5 *        78 *           *
*        1 *        6 *        78 *        75 *
*        1 *        7 *        78 *           *
*        1 *        8 *        78 *           *
*        2 *        0 *        11 *        11 *
*        2 *        1 *        78 *        75 *
*        2 *        2 *        78 *        75 *
*        2 *        3 *        78 *           *
*        2 *        4 *        78 *           *
*        2 *        5 *        78 *           *
*        2 *        6 *        78 *           *

but this can be explain with you remark.

Now, to rephrase myself and be more specific : I would like to plot x[1] function of x[0] with a condition on n. For example :

test->Draw("x[1]:x[0]","n==3")

While doing this, I obtain results that does not look like at all what I expect. The result looks more like what I would obtain if I use “as is” the data dumped by Scan.
How can I perform the plot I want ?

Regards
Julien

Hi Julien,

Semantically ‘x[0]’ is still an array and TTree::Draw chose to assign by default the fixed value to the left most array dimension. Thus (see the TTree::Draw documentation for all the gory details), you expression is akin to test->Draw("x[1][]:x[0][]","n[]==3")or in other word:x[1][Iteration$]:x[0][Iteration$]","n[Iteration$]==3". I think you are looking for:test->Draw("x[][1]:x[][0]","n[]==3")to explicit which of the dimension TTree::Draw should loop over.

Cheers,
Philippe.

Philippe,

Thank you for your answer. Indeed it works.
I tried first the other way (x[1][]:x[0][]) : it would have worked in Fortran not C++ !
Then when I looked at Scan I got definitely confused…

Thanks a lot : (basic) problem solved.

Regards
Julien