TTree with class and array

Dear all,

I’ve crossed this problem several times. And I am not sure how to deal with it.
Please, find attached an example script to reproduce the problem (execute example_tree_write.C and then example_tree_read.C.

To better describe the problem:
When I create an array of length 100 but save only the first 10 points, it will save the array properly, but anything that comes after it will not be saved (in the example, selection)

I would like to keep the class structure as all my analysis is based on this (in my complete scripts I have several channels and need to work with something very similar to the example).

I cannot invert “selection” with “wvf” as they have different type and the data will not be saved properly.

What am I doing wrong?

Best regards,
Henrique


ROOT Version: 6.26/06
Platform: Ubuntu 24.04
Compiler: g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0


example_tree_read.C (855 Bytes)
example_tree_write.C (985 Bytes)

example_tree_write.cxx (1.0 KB)
example_tree_read.cxx (1.3 KB)

Dear Wile,

This solution is (almost) perfect! Thanks.
The only problem is that I still need to define the size of the array during compilation. The best solution I was searching was to define the length inside some function, but I believe that is not possible at all (without using vectors). However, declaring the class with the template is of great help.

Thanks again!

template <Int_t npts = 100>
class MY_DATA {
public:
  // note: tree branch variables must be sorted in the decreasing order of size
  Int_t actualSize = npts;
  Int_t selection;
  Double_t peak;
  Double_t wvf[npts];
  
  std::string tobranch = "actualSize/I:selection/I:peak/D:wvf[actualSize]/D";
  
  MY_DATA();
};

MY_DATA.hxx (1.3 KB)
example_tree_write.cxx (898 Bytes)
example_tree_read.cxx (941 Bytes)

Thanks!
Although this works to have different sizes of vector, I still have to declare the size in the time of compilation.

Thank you again Wile.

This is a great solution, however I have several channels and I keep the variables declared in the class holding the info for each channel.
So, I prefer to use each class as a branch.
For instance:
The class MY_DATA as ch0 and ch1.
For each waveform I have saved, I have informations like charge, peak, selection, etc.
I hope this makes sense :slight_smile:

So, with my last “example”, you just need to change the "prefix", e.g.:
MY_DATA ch0, ch1; ch0.Branch(tree, "ch0_"); ch1.Branch(tree, "ch1_");

Alright! Sorry my bad.
Thank very much

A more canonical (better?) approach …

MY_DATA.hxx (648 Bytes)
example_tree_write.cxx (1.1 KB)
example_tree_read.cxx (1.4 KB)

Dear Wile,

Yes! This is even better.
I had no idea how to work with class + pointer. This is the solution I wanted from a long time, but I could not figure out in the documentation by lack of knowledge in C++.

Thanks a lot!

Dear @Wile_E_Coyote

I noticed now, in order to work, MY_DATA.hxx needs the comment at line 11:

  Double_t *wvf; //[npts]

(For both, reading or writting)
I never saw this before, do you have any explanation for that?

Sorry to keep on the topic.

Cheers,
Henrique

ROOT Manual → Functional parts → I/O concepts → ROOT’s C++ object serialization: from memory to disk and back → Array data members of fixed and variable size

1 Like

Thank you and sorry for the silly question :slight_smile: