Issues with automatically constructed MakeSelector

I am making a new topic since the topic I originally replied to for this issue was 2 years old, and quite stale.
This issue is based on information in this very dated issue here.

I am using a TSelector generated by root, but am having trouble with it.
When I try to run the selector, ROOT complains about the types used and crashes.

TTreeReaderValue<ULong64_t> event = {fReader, "SelectOpHitBkgInfo.event"}; 
TTreeReaderValue<ULong64_t> run = {fReader, ""}; 
TTreeReaderValue<ULong64_t> subRun = {fReader, "SelectOpHitBkgInfo.subRun"};

When I try to run the selector in ROOT (v6.18), I am presented with an error:

root [0] TChain* ch = new TChain("pduneMuonLifetime/OpHitBkgTree")
(TChain *) 0x55aa6129d3f0
root [1] ch->Add("~/PDune_ReproV28/pdune_reco_repro_opPatch_SMu_np04_raw_run005*.root")
(int) 14
root [2] ch->Process("BKGSelection.C+g")
slave begin
Hists made
Getting Entry from reader
Error in <TTreeReaderValueBase::CreateProxy()>: Leaf of type ULong64_t cannot be read by TTreeReaderValue<unsigned long long>.

Here is a print() of my TTree.

root [4] OpHitBkgTree->Print()
*Tree    :OpHitBkgTree: Select Op Detector Hit info for backgrounds.           *
*Entries :   103099 : Total =         9106593 bytes  File  Size =    2408312 *
*        :          : Tree compression factor =   3.78                       *
*Br    0 :SelectOpHitBkgInfo : deltat0/D:deltat/D:t0/D:te/D:tabs/D:PEs/D:    *
*         | event/l:run/l:subRun/l:chan/l:bar/l                              *
*Entries :   103099 : Total  Size=    9106120 bytes  File Size  =    2405000 *
*Baskets :      285 : Basket Size=      32000 bytes  Compression=   3.78     *

The struct used to fill it uses the same types as listed in the documentation for TTree.```

    D : a 64 bit floating point (Double_t)
    l : a 64 bit unsigned integer (ULong64_t)

And the struct I use to fill.

167 struct ohitinfo
168 {
169   double  deltat0 = -999999999.9;
170   double  deltat  = -999999999.9;
171   double  t0      = -999999999.9;
172   double  te      = -999999999.9;
173   double  tabs    = -999999999.9;
174   double  pes     = -999999999.9;
175   uint64_t event   =  999999999;
176   uint64_t run     =  999999999;
177   uint64_t subrun  =  999999999;
178   uint64_t channel =  999999999;
179   uint64_t bar     =  999999999;
181   void reset()
182   {
183     deltat0 = -999999999.9;
184     deltat  = -999999999.9;
185     t0      = -999999999.9;
186     te      = -999999999.9;
187     tabs    = -999999999.9;
188     pes     = -999999999.9;
189     event   =  999999999;
190     run     =  999999999;
191     subrun  =  999999999;
192     channel =  999999999;
193     bar     =  999999999;
194   }

I am a bit at my wits end, since this appears to be an extremely simplistic use case for both TTree and TSelector, but I am unable to process any of my analysis.

This is likely related to the use of a ‘leaflist’ to create the branch.
Branches like:

*Br    0 :SelectOpHitBkgInfo : deltat0/D:deltat/D:t0/D:te/D:tabs/D:PEs/D:    *
*         | event/l:run/l:subRun/l:chan/l:bar/l                              *

are “usually” sub-optimal as the data is always stored ‘together’ and thus reading ‘just’ one or two values (for example event and delta) means that you actually must read all values at once.
I.e. you may be better off creating 11 separate branches instead (if you were to genereate a dictionary for the struct ohitinfo, this splitting would be done automatically for you).

That said this sounds like a bug … let me see if I can reproduce it (you can speed up the process by providing an example file).


jstock_example.root (6.2 KB)
BKGSelection.h (4.2 KB) BKGSelection.C (4.2 KB)

I run this manually with the following lines from my root hist:

 TChain* ch = new TChain("pduneMuonLifetime/OpHitBkgTree")

As to your recommendation about generating multiple branches, what would my code to make the change need to look like? That that be done just by defining the split level or do I need to declare 11 branches?

That depends a bit of how your write the file (script, compiled script, library).

If you have a script (and want to keep it that way) you could either need to separate the struct in separate file and compile that file with ACLiC (hence getting easily a dictionary for ohitinfo) and then ‘just’ doing:

tree->Branch("ohitinfo", &hitinfo_object);

will do it.
If you can not generate a dictionary for the struct then, indeed, you need to create by hand 11 branches and given them each the address of the individual data members.


PS. The deficiency will be fixed shortly


Is there a work around for now that will make my files readable without reproducing them?

You can use the older selector implementation (which does not use the TTreeReader)

ch->MakeSelector(filename_prefix, "=legacy");


Thank you. That will save me a lot of time.

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