Help on Method/s to create Tree from multi-fold gamma-ray coincidence data

_ROOT Version: 5.34/09
_Platform: Linux 3.11.10-100.fc18.x86_64
_Compiler: gcc version 4.7.2 20121109 (Red Hat 4.7.2-8) (GCC)


I need a help on the topic mentioned in the subject line. Here is the description of the problem:

I am working on the analysis of the data generated in a gamma-spectroscopy experiment. In the experiment, we had 24 detectors. We get ENERGY and TIME information from ONLY those detectors which have detected a gamma-ray in a given event, which also defines fold of an event (i.e. number of detectors which have registered the events). Also, the fold varies for different events, and I have about 100 data files.

First, I want to convert the data into ROOT Tree format for all the files, and later I will use this tree to generate different 1-D, 2-D, and 3-D histograms, with different conditions (using timing information).

Can someone please help me with guidelines/recipe to generate a Tree out of “Energy, Time and Event”? What is the best way to convert the above data into ROOT Tree? What should be the structure of the tree?

I am sorry, if this sounds too obvious. Please note that - this is my first attempt to try data analysis using ROOT, and to create Tree!

Any help/guidance is highly appreciated.

With best regards,


Hi Ajay,

can you share one of the files you have?
As a side comment: could you move to ROOT 6.14? ROOT 5.34 is not developed any more.


Thank you very much Danilo.

I plan to move to ROOT 6.14 soon.

I am sorry, but the data files which I have are in a customize binary format. I had already written a code which will extract “ENERGY and TIME” for number of detectors in “FOLD”. For example, if we consider a specific event has FOLD = 3, then I will have 3 ENERGY and 3 TIME signals.

Hi Ajay,

I see. Do you have code to read these binary files (Python, C, C++)? This “adapter” will be needed irrespective from the ROOT part of the solution :slight_smile:


Thanks for the prompt reply.

I am poor in programming! The code which I have is mostly(!) in C++. Mostly - because I said I am a poor programmer and some parts of it may also have some “C” in it :slight_smile:


Hello Danilo,

Do you need anything else from me? Waiting for your reply.



I guess you would need to provide one of your binary data files and the source code which you have for reading it.

I will be happy to share all the required information with you. But please note that the data files are of 300MB. Can you suggest me a way to share? Can I simply upload it here?


I am sharing a link to a .tgz file which contain all the information needed. But please forgive me for my poor coding techniques.




I think the best way is to try to take your code which reads your binary format and marry it with RDataFrame. More in detail, the skeleton could be:

auto N = 123 ; // <- Here the number of events
ROOT::RDataFrame d(N);
d.Define("Energy", yourFunctionReturningEnergy).Define("Time", yourFunctionReturningTime).Snapshot("mytree", "mydataset.root");



Thank you.

But I am looking for a simple and traditional way of generating a Tree. As you might have noticed from the code that - I am already extracting the information and filling histograms as follows:

(1) Filling timing spectra : his_TDC[n]->Fill(CLT[n]);
(2) Filling energy spectra: his_AB[n]->Fill(Eclab[n]);
(3) Getting multiplicity with: clov_mult = cl_mult.count();

I am not sure how to use RDataFrame, and also won’t be able to spend time on it at the moment.



Are you able to open the files?

The attached source code shows how you can save / retrieve “clovers” in / from a TTree (note: if you want a “non-zero-suppressed” TTree, add -D_ZERO_SUPPRESSION_LEVEL_=0 when compiling “canSort_new.cxx”).

It seems that ROOT 5.34 (using the ZLIB level 1 by default) achieves about three times better compression than ROOT 6.14 (using the LZ4 level 4 by default) without any significant difference in execution times so, with ROOT 6 one should always remember to enforce the compression algorithm and its level (which is usually not needed with ROOT 5), e.g.:

f = new TFile(hisfile, "RECREATE", "", 101); // 101 = 100 * ROOT::kZLIB + 1

One can further improve the compression by another factor two if one enforces LZMA (unfortunately, this will also double the execution time but, it may really be worth to bear it), e.g.:

f = new TFile(hisfile, "RECREATE", "", 201); // 201 = 100 * ROOT::kLZMA + 1

Note: The “man lzma” says that the “compression preset level” can be “-0 … -9”. It seems to me that ROOT is unable to use the “-0” (i.e. the “–fast”) level. When one tries “compress = 200” (= 100 * ROOT::kLZMA + 0), one gets uncompressed ROOT files. Manual trials show that ROOT files compressed with “-0” are almost the same size as with “-1” but the time needed is around 20% shorter (at least). So, it would really make sense to modify ROOT so that it recognizes “compress = 200” as “LZMA @ -0” (or maybe one could set the “actual LZMA level” = “ROOT LZMA compression - 1”, so that “201” would be “-0”, “202” would be “-1” and so on).

canSort_new.cxx (45.6 KB)
canSortTTreeDump.cxx (2.8 KB)

1 Like

Your help and time is highly appreciated. It will certainly help me. I can see that you have been working on this all the time since I have posted the code :slight_smile:




I was just wondering - why is there “&” before “clov_mult” and “No_Clover” when you define Branches, while it is missing in others.

May be it is a stupid question?


That’s “simple variables” versus “arrays” (and anyhow, for these arrays, writing &array is equivalent to writing simply array, you can try if you want).

Note that in the above “canSort_new.cxx” source code _clov_mult_ = clov_mult; so I could use the original clov_mult variable everywhere. But I decided to introduce a separate _clov_mult_, just for the TTree, in case you wanted to change its value / meaning in future (so that the original clov_mult could remain unchanged).

1 Like

Okay. Thank you once again.

Wow! That’s great.

I have modified the code so that the histograms are filled in a specific way. I am attaching the modified version of the code, just in case you plan to work on it further.

Thank you very much.

can2root.cxx (43.7 KB)

I think we have a small problem:

I have compiled the code with -D_ZERO_SUPPRESSION_LEVEL_=2, and then ran it to generate a root file.
After this, when I dumped “non-zero” entries only, I still get zeros as shown below:

1 : 1 : 1 : ( 8 : 0 , 458 ) <======== here CLT[8] = 0

75 : 1 : 2 : ( 2 : 2885 , 0 ) ( 12 : 2902 , 245 ) <======== here Eclab[2] = 0

Ideally, all those events are valid in which both CLT[j] and Eclab[j] are non-zero.

Attaching, “modified” version of the code again.


can2root.cxx (43.7 KB)

You seem to miss the point … see what’s after the line #if (_ZERO_SUPPRESSION_LEVEL_) > 1.

If you want to require that both “CLT” and “Eclab” are non-zero, replace the line (“pass” if non-zero “CLT” OR “Eclab”):

if ((CLT[n] == 0) && (Eclab[n] == 0)) continue;

with (“pass” if non-zero “CLT” AND “Eclab”):

if ((CLT[n] == 0) || (Eclab[n] == 0)) continue;

BTW. Note that “clov_mult” seems to be strictly related to non-zero “Eclab” only (i.e. it doesn’t care about “CLT”).