Data Structure Question - Storing Data per Event

I am new programmer and have a question about the optimal way to store my data in root. Here is the simplified situation:

I have many events. Each event can have up to N pulses. I would like to store some parameters about each pulse on a “per event” basis, as well as some data about the event as a whole. For example, each event has N pulses that each have an amplitude and time, and each event also has a trigger time.

Right now, the data is stored on a “per pulse” basis in TNuple:

The algorithm then iterates through each event, and for each event, it iterates through the number of pulses in the event.

The result is a repetition of the same event number in the TNtuple. The advantage to this method is that, if I want to see all the pulse data, I can say ntp.Draw(“pulseAmpltiude:pulseTime”). The disadvantage is that the data isn’t stored logically on a per event basis as one would expect.

So I am trying to use a TTree. In this case something like:

[code]struct Data{
int event;
float triggerTime;
std::vector pulseAmp;
std::vector pulseTime;
NtpData() : pulseAmp(5), pulseTime(5) {}
} fDataStruct;

fDataTree = new TTree(“fDataTree”, “fDataTree”);
fDataTree->Branch(“fDataStruct”, &fDataStruct, “event:triggerTime:pulseAmpltidue:pulseTime”);[/code]

The disadvantage to this method is that I can no longer visualize the data with the built-in Draw command from ROOT, since ROOT recognizes the leaves of the TTree as vectors and not the floats that are in the vectors.

I am wondering if there is a way to do what I would like: store all my data per event, but still be able to directly plot something like Draw(“pulseAmpltiude:pulseTime”).

If it matters: I am dealing with ~1e6 events, each with up to 8 pulses.

Thank you for your time.

ROOT User’s Guide -> Trees -> Example 2: A Tree with a C Structure -> Writing the Tree -> Adding a Branch with a Variable Length Array
Try: [code]#include “TFile.h”
#include “TTree.h”
#include “TRandom.h”

const unsigned int kMax_Ntp = 8;

struct Data {
Int_t event;
Float_t triggerTime;
UInt_t Ntp; // note: Ntp MUST be <= kMax_Ntp
Float_t pulseAmp[kMax_Ntp];
Float_t pulseTime[kMax_Ntp];
} fDataStruct;

void trial(void) {
TFile *f = TFile::Open(“fDataFile.root”, “RECREATE”);
TTree *t = new TTree(“fDataTree”, “some tp data”);

t->Branch(“event”, &fDataStruct.event, “event/I”);
t->Branch(“triggerTime”, &fDataStruct.triggerTime, “triggerTime/F”);
t->Branch(“Ntp”, &fDataStruct.Ntp, “Ntp/i”);
t->Branch(“pulseAmp”, fDataStruct.pulseAmp, “pulseAmp[Ntp]/F”);
t->Branch(“pulseTime”, fDataStruct.pulseTime, “pulseTime[Ntp]/F”);

for (int i = 0; i < 1000; i++) {
fDataStruct.event = i;
fDataStruct.triggerTime = 100.0 * i;
fDataStruct.Ntp = UInt_t((1.0 + kMax_Ntp) * gRandom->Rndm());
// just a precaution (Ntp MUST be <= kMax_Ntp)
if (fDataStruct.Ntp > kMax_Ntp) fDataStruct.Ntp = kMax_Ntp;
for (int j = 0; j < ((int)(fDataStruct.Ntp)); j++) {
fDataStruct.pulseAmp[j] = gRandom->PoissonD(10);
fDataStruct.pulseTime[j] = gRandom->Gaus(10);

delete f; // automatically deletes “t”, too

Thank you. That was very helpful and exactly what I needed.


I have a problem similar to ohmartn’s, but my case is a little more complicated.

I want to store the output of an acquisition system into a ROOT file; the acquisition can use several cards, each one with its number of channels. The events of each channels are made of several single variables, and one (or more, in the future) array of N samples - N can change at every acquisition.

Right now I am using trees to represent cards, branches to represent channels, and one entry for each event. The array of samples is the last field of the associated struct.

If I understand correctly the above sample, trees are used to represent channels; I need ad additional level to differentiate the cards…

I was thinking about using STL vectors… what do you think about it?

EDIT: I keep looking in the forum… I just found that vectors may be a good idea:
[ … ays#p76165](TTree: multiple variable length arrays
I’ll try!