How to get all values of a TTree (Ntuple) branch?

Dear ROOT experts,

I have a TTree (Ntuple) with only about 20 branches, but 10^9 entries (each branch has equal entries). The run number (integer) is among these 20 branches, and we know that there are only several hundreds of runs. So, is there an easy way to get the list of runs, or to get all values of a TTree branch (yes, here it the run number)?

The easiest and fast way I know is that

  1. get the maximum and minimum values of the run number
  2. book an histogram with total bins of (maximum value - minimum vlue) and corresponding range, etc.
  3. project “run Number” to this histogram
  4. loop all the bins of this histogram and keep the GetBinCenter of the bin with non-zero entries.

But I think there must be a more smarter way to do so.

Many thanks in advance.

I would try the following:

std::set< int > runNumberSet;
loop over entries:
   // get run number
   runNumberSet.insert (runNumber
// end loop

// use set here (you can iterate over a set like a vector

The advantage of a set is that it keeps track of whether it has seen an entry or not and will give you the run numbers in sorted order (see cppreference.com/wiki/stl/set/start for more details).

Cheers,
Charles

The fastest solution

mytree->Draw("run>>hrun"); TH1 *hrun = (TH1*)gPad->GetPrimitive("hrun"); then procedd like in your step 4

Rene

[quote=“brun”]The fastest solution

mytree->Draw("run>>hrun"); TH1 *hrun = (TH1*)gPad->GetPrimitive("hrun"); then procedd like in your step 4
[/quote]

The “problem” with this is if you have a large run range that is sparcely populated. You can get around this problem by specifying the binning:

At some point, however, your run range may be such that the number of bins becomes somewhat silly. In this case, you can also use the Draw to do the loop for you and grab the results using TTree::GetSelectedRows() and TTree::GetV1() and using the set like I proposed before.

Cheers,
Charles

Hi, Rene,

[quote=“brun”]The fastest solution

mytree->Draw("run>>hrun"); TH1 *hrun = (TH1*)gPad->GetPrimitive("hrun"); then procedd like in your step 4

[/quote]

I did a test just now. This doesn’t work. The automatic bin size caused trouble. To get correct results, we need to book a histogram with a total bins of (maximum-minimum), as what I did:

Double_t firstRun = t1->GetMinimum("runNumber"); Double_t lastRun = t1->GetMaximum("runNumber"); Int_t totalBins = (lastRun - firstRun)+10 ; TH1I *hrun = new TH1I("hrun", "run number", totalBins, (firstRun-4.5), (lastRun+5.5) ); t1->Project("hrun", "runNumber");

It only took several minutes to get the results.

To Charles, I will try your suggestion, but I guess it will not be fast than the above solution. You know, I tried std::vector, it was very, very slow.

Thanks, Jibo

Right. You can set the binning explicity when you do the draw (see my second message).

A vector is the wrong thing since it will happily let you have multiple entries. A set is ideal for this job (and you can even use a std::map if you want to keep track of how popular each run is.

Cheers,
Charles

Hello,

Just want to let you know that this approach works very well. It also only takes several minutes to get the run number sets.

Of course, I would not only use vector. I tried something like:

[code] // first see if the value is in cache
map<int,size_t>::const_iterator foundCache = runsCache.find(runNumber);

if (foundCache == runsCache.end()) // not found
{
vector::const_iterator found = find(runs.begin(), runs.end(), runNumber);
if(found!=runs.end()) // found
{
// cache the value with its position
runsCache[runNumber] = found - runs.begin();
} else //not found
{
runs.push_back(runNumber);
}
}[/code]

I guess it is not as efficient as std::set. Also, I put it in a MakeSelector->Process block, maybe this also causes inefficiency?

Many thanks.

Cheers, Jibo

Hi Jibo,

With your attempt using an std::vector, you are trying to implement std::set by hand. I can easily believe that since std::set has been optimized to do this, it will be much faster than trying to use the wrong tool for the job.

There is an expression “When you have a hammer, everything looks like a nail.” Well, now you have a wrench in addition to your hammer. :smiley:

Cheers,
Charles