Individual branch fill in tree in a loop

Hello Everyone,
I have to create a tree with several branches so I use sprintf() inside loop to create branches in a new root file. I am able to create tree with several branches using: sprintf(branch, “branch%d”, i) and tree->Branch(branch, &branch[i], “…”) within a loop using tree->Fill(). My branches within the tree are branch1, branch2,…with the same leaf variables in each branch.
I would like to use the branch->Fill() instead of tree->Fill(), but I could not do this in the loop. If I use branch->Fill(), I got an error: "no member named ‘branch’.
Could anyone please help me to fill branch individually within loop?
Thank you in advance,
JP

Hi JP,
it’s hard to say what the problem is with just this information. Can you please try to reduce the issue to the smallest snippet of code that still compiles and reproduces your problem, and then post it here?

Also, in order to better understand what you are trying to achieve: why do you wish to call branch->Fill instead of tree->Fill?

Hello,
I have a text file which contains a data set of several events (let’s say 100): each event containing data of some channels( say 20 channels) with every channel having different (say 30) data values in every event. So first event is considered as first 600 (20 times 30) entries in the text file which belongs to 20 different channels. Then for second event, next 600 entries; then 3rd event and so on in the text file.
Now, I am creating a ttree from this file with events as branch and ‘channel with data’ as leaf. For this I took a structure of 21 members (1 for order of data set and 20 for each channel). The code I am using right now looks like the attached below:tree.c (1.9 KB)
This code is only a sample code for my work. I actually have more events to analyze with more channels and more data values. So if I take a tree->Fill(), it updates every branch and the buffer seems to be full soon. Every Fill() tries to fill all the branches, but I want to fill the branches one by one. For example while using the code above, the first brach (Event1) is filled from the beginning to the end; which needed large buffer as well as a long time to update.
So instead I would like to use the branch->Fill() in my case, however I could not use it. While using event->Fill(), I got error message of no member named ‘event’.
Is it possible to fill branches individually in my case?
Thank you,
Jiwan

Hi Jiwan,
let me see if I understand. I usually think of a TTree as a big table with rows and columns. Each cell contains some data.
One event is a row of the table.
Each leaf is a column.
Branches are columns that contain structured data (i.e. more complicated leaves).

If I understand correctly you want to fill only certain branches for a given event, but that would mean filling only certain columns for a given row. It does not seem ideal. In this light, I think it is also a bit more clear that when you say that you want “events as a branch” that is a very confusing statement for me :sweat_smile:.

The simplest way you can put your data in a tree is with one leaf per “channel_X_data_Y”, for a total of 600 leaves and 100 events. If you want to group data pertaining to the same channel together, you can have 20 branches (one per channel) with 30 leaves each (one per data), again with 100 events.

In both cases, you would want to fill all branches for each one of the events: you want to fill all columns for each row of your data table.

In terms of your tree.c script, you are now creating only one column/branch “sample” which contains 20 integer values for each event/row. I think what you want is creating many more columns/branches (600 or 20, see above) and fill them with all of your 600 data elements for each event.

Am I missing something?
Cheers,
Enrico

Hello Enrico,
The word “event” that I used here is confusing. The ‘event’ I am referring for is not same as “One event is a row of the table”. Sorry about this. So I think it is better to call “events” as “signal_out”.
So in brief, I need an output ttree which should have signal_out_1, signal_out_2, signal_out_3…separately. Each signal_out contains data of 20 different channels in separate row/column. My aim is to make a single ttree which holds all the signal_out. So, I have every branch with 20 leaves (for 20 different channels) which contains 20 integers as its first entry in one branch. In another way, my tree looks like:


All the leaf have equal number of entries (30). As branch looks separate, I want to fill all the leaves of Branch1 first and then branch2 and so on.
I am sure I messed up in my code to do so and get a such tree. I am thankful for your help. Please, could you elaborate more?
Regards,
JP

Alright, so the logic you want to implement is the following (note that I have not tested the code, I am writing it out for demostration purposes):

// the type of your branches
struct SignalOut { int channels[30]; };

void CreateTree() {
  // create output file and output tree
  TFile f("sample.root", "RECREATE");
  TTree t("signal", "signal");

  // create signal_out branches
  std::vector<SignalOut> signals(20); // a vector of 20 SignalOut structs
  for(int i = 0; i < 20; ++i) {
    auto branchName = "signal_out_" + std::to_string(i+1);
    t.Branch(branchName.c_str(), &signals[i]); // bind each SignalOut struct to a different branch
  }

  // input file
  ifstream inputFile("sample.asc");

  // loop over data, fill tree
  while(!inputFile.eof()) {
    // here goes your logic to update the values of ALL 20 SignalOut structs "signals", for example:
    for(int i = 0; i < 20; ++i) // for each signal
       for(int j = 0; j < 30; ++j) // for each channel 
          inputFile >> signals[i].channels[j];
    t.Fill(); // store this row
  }

  // cleanup
  t.Write();
  f.Close();
}

Hope this helps,
Enrico

Quite impressive. I have little problem with this because my sample.asc file contains data on the other way. You put the entry from the asc file into channels, which seems reasonable as they repeat in the same way. However, after the first loop “for(int j = 0; j < 30; ++j)” the data obtained from the asc file belong to the next row of the same columns, not the same row with different columns. I mean I have asc file which has first 600 entries belonging to signal[1], then only for signal[2]: next 600 and so on.
So, I have doubt that this code provide me correct output. Could you look at this code again?
Thanks,
JP

I see. Alright I think I understand the situation finally :smile: I’ll try to think of something.

Just to clarify once and for all, your input file has format:

entry1_signal1_ch1
...
entry1_signal1_ch30
entry2_signal1_ch1
...
entry2_signal1_ch30
...
entryN_signal1_ch30
entry1_signal2_ch1
...
entry1_signal2_ch30
entry2_signal2_ch1
...
entry2_signal2_ch30
...
entryN_signal20_ch30

Correct? If yes, how large is N?

Yes, you are right about the input file format. N could go upto 255 (maximum). In addition, both ‘signal’ as well as ‘ch’ could also increase; for example ch can go up to 64.

So we are talking about a maximum of one million (2556464) integers. That is nothing when loaded in RAM (about 8 MB). One solution is you just parse your file once, load everything into memory (in array variables) and then use those arrays to fill the tree (i.e. substitute reading from the input file (inputFile >>) with accessing the right data in your variables).

I also finally understand your original question: “how to fill a TTree with 255 entries one branch at a time: first fill all entries for the first branch, then all entries for the second branch, and so forth”. I actually do not know if this is supported – maybe one of @Axel, @pcanal and @dpiparo knows.

Hi,

What about a tree with the following branches?

  • entry
  • signal
  • channel

Cheers, Axel.

Thanks for the suggestion. I was doing the same way with 4 different branches (as you suggested) to analyze my data.
While doing so I wanted to do differently as discussed in previous emails.

I don’t see an advantage in doing that, or I’m misunderstanding the pattern.

You can think of a TTree as a vector of a class. I understand that your “class” has the members you show in your nice graphics. But I fail to see how it contains more than one “object” of that “class”. Do you measure multiple signals, each with different values for signal_out1/ch1, signal_out1/ch2, … signal_out3/ch1, signal_out3/ch2,…?

If neither the signal nor the channel numbers are fixed then you’re better off storing vectors, along the lines of this class structure:

struct signal_out {
  vector<float> fChannels;
};
struct signal {
  vector<signal_out> fSignalOuts;
};

If you create a branch for signal it will contain a runtime-defined number of Signal_out_N, each with a runtime-defined number of channels.

Cheers, Axel.

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