Std.vector('bool') and TTreeFormula::EvalInstance()

Hi.

I’m experiencing an issue using EvalInstance() with a std.vector(‘bool’) element in my tree.

The two different outcomes:

  • When define a variable, set the branch address and read the tree, I get correct output.
  • When I define a TTreeFormula and subsequently evaluate it, the output is only correct for the first two elements of the vector (0, 1). For all further elements (eg. 2, 7, but also the others) I just get false/0.

I made a minimal working example with two example trees, and a piece of code which outputs a table allowing to compare ‘reading variable from tree directly’ vs. ‘using EvalInstance()’. If anyone could have a look and help me figure this out, that would be great.

Thanks,
Sara

Note: clone1.root is cloned from a file which I didn’t create myself, hence I didn’t fully trust it. I made a similar tree in tree1.root, just defining a std.vector(‘bool’)() and filling it in a short loop. Nothing can go wrong there, can it?

The output when I run my example:

******************************************************************************
*Tree    :tree      : tree                                                   *
*Entries :       20 : Total =            1464 bytes  File  Size =        562 *
*        :          : Tree compression factor =   3.45                       *
******************************************************************************
*Br    0 :myvar     : vector<bool>                                           *
*Entries :       20 : Total  Size=       1078 bytes  File Size  =        174 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   3.45     *
*............................................................................*
******************************************************************************
*Tree    :tree      : tree                                                   *
*Entries :      100 : Total =            3544 bytes  File  Size =        904 *
*        :          : Tree compression factor =   5.22                       *
******************************************************************************
*Br    0 :myvar     : vector<bool>                                           *
*Entries :      100 : Total  Size=       3158 bytes  File Size  =        513 *
*Baskets :        1 : Basket Size=      32000 bytes  Compression=   5.22     *
*............................................................................*
TREE 1
                    fromVar  |                    withEval
     0      1      2      7  |      0      1      2      7
./test02.py:41: RuntimeWarning: creating converter for unknown type "const char**"
  print "%6s"%(ttf1[j].EvalInstance()),
  True   True   True   True  |    1.0    1.0    0.0    0.0  
  True  False   True  False  |    1.0    0.0    0.0    0.0  
  True   True   True   True  |    1.0    1.0    0.0    0.0  
  True  False   True  False  |    1.0    0.0    0.0    0.0  
  True   True   True   True  |    1.0    1.0    0.0    0.0  
  True  False   True  False  |    1.0    0.0    0.0    0.0  
  True   True   True   True  |    1.0    1.0    0.0    0.0  
  True  False   True  False  |    1.0    0.0    0.0    0.0  
  True   True   True   True  |    1.0    1.0    0.0    0.0  
  True  False   True  False  |    1.0    0.0    0.0    0.0  
TREE 2
                    fromVar  |                    withEval
     0      1      2      7  |      0      1      2      7
 False   True  False   True  |    0.0    1.0    0.0    0.0  
  True  False  False  False  |    1.0    0.0    0.0    0.0  
  True   True  False   True  |    1.0    1.0    0.0    0.0  
  True   True  False   True  |    1.0    1.0    0.0    0.0  
  True   True  False   True  |    1.0    1.0    0.0    0.0  
  True  False  False  False  |    1.0    0.0    0.0    0.0  
  True   True  False   True  |    1.0    1.0    0.0    0.0  
  True   True  False   True  |    1.0    1.0    0.0    0.0  
  True  False  False  False  |    1.0    0.0    0.0    0.0  
  True   True  False  False  |    1.0    1.0    0.0    0.0  

clone1.root (5.96 KB)
tree1.root (5.62 KB)
test02.py (1.21 KB)

Hi,

to make sure it was a limitation of TTreeFormula::EvalInstance(), rather than a python problem, I rewrote part of your python script in C++ and observe the same behavior.

Note that std::vector is allowed to be a specialization per the C++ standard, so it’s memory layout may be not as natural as other instantiations of std::vector.

I’ve pinged Philippe, maybe he knows more.

Cheers,
Wim

Hi,

Thanks. I should have mentioned that this also appeared in a C++ version, but I entirely forgot. Apologies.

Additionally, as far a I know with other types of std::vector this issue doesn’t occur (I have configurations with length 4 int and float vectors and there it works fine) so you’re probably hitting the nail on the head with your remark about the different properties of std::vector.

Please let me know if I can help provide additional information, because I would really like to solve this problem or at least understand it more fully.

Cheers,
Sara

Hi,

In the usage of TTreeFormula you are missing a call that is essential if the formula has a variable number of values (When using a std::vector, by definition you have a variable number of values; if you request a specific index it might still be out of range in which case there is zero value for the formula).

You need something like:

for j in [0,1,2,7]: if (ttf2[j].GetNdata() > 0): print "%6s"%(ttf2[j].EvalInstance()), print " "

Cheers,
Philippe.

PS. Note that technically the code using the vector directly has a similar problem (the code access the index without checking it is in range …), however for TTreeFormula GetNdata has additional side-effect (it initialize the formula itself for this entry and hence it is required).