No typo checks in TTreeFormula

Hello ROOT team,

for the (dont-know-how-many)th time I made a typo and got wrong results from ROOT instead of an error.

If you have a branch with some leaves, it seems the TTreeFormula is not checking for correct names and just returns whatever it likes (first leaf in branch?). This also happens in Tree->Scan or in TMVA’s AddVariable function (which is super annoying if you notice it after some hours of training).

Is this intended behaviour? Can ROOT (or I myself) somehow check that a TTreeFormula is valid? I tried GetNdim, but that returns 1 even for non-existing leaves

Example code to reproduce:

[code]#include <TCanvas.h>
#include <TFile.h>
#include <TTree.h>
#include <TTreeFormula.h>

using std::cout;

struct S {
Float_t f1;
Float_t f2;
};

void bug() {
S s = { 23.f, 42.f };
TTree t(“t”, “t”);
t.Branch(“b”, &s, “f1/F:f2/F”);
t.Fill();
new TCanvas;
t.Draw(“b.f1”);
new TCanvas;
t.Draw(“b.fNonExistant”); //root is happy to draw this as well!

TTreeFormula f1("f1", "b.f1", &t);
cout << f1.GetTitle() << " -> dim = " << f1.GetNdim() << '\n';
cout << "Title of b.f1 is " << f1.GetLeaf(0)->GetTitle() << '\n';

TTreeFormula f2("f2", "X.f1", &t);
cout << f2.GetTitle() << " -> dim = " << f2.GetNdim() << '\n';

TTreeFormula f3("f3", "b.fNonExistant", &t);
cout << f3.GetTitle() << " -> dim = " << f3.GetNdim() << '\n';
cout << "Title of b.fNonExistant is " << f3.GetLeaf(0)->GetTitle() << " - WAT?!\n";

cout << "\nNow scanning the tree\n";
t.Scan("b.f1:b.WAT:b.f2:b.a_typo");

}
[/code]

The result is:

[code][11:44:13] ~/test$ root bug.cpp
root [0]
Processing bug.cpp…
b.f1 -> dim = 1
Title of b.f1 is f1
Error in TTreeFormula::Compile: Bad numerical expression : "X.f1"
X.f1 -> dim = 0
b.fNonExistant -> dim = 1
Title of b.fNonExistant is f1 - WAT?!

Now scanning the tree


  • Row * b.f1 * b.WAT * b.f2 * b.a_typo *

  •    0 *        23 *        23 *        42 *        23 *
    

[/code]

Hi,

This is restricted to the leaflist case (your case) and does not affect the object case.

Unfortunately, the code explicit allow for this alias (of a bad name to the first leaf name). It might be related to some (earlier) weakness in the parsing and be a leftover. Since this is explicitly allowed by the code, no error message is recorded and short of checking that the leafname you got is the one you wanted there is no way to detect this.

This is of course a problem and thus I opened a JIRA ticket: sft.its.cern.ch/jira/browse/ROOT-8577

Cheers,
Philippe.

Hi,

I fully support the answer of Philippe.
I just wanted to add that presently, in the master of ROOT, there is a utility which offers an interface which is a bit more complex than the one of TTree::Draw but in exchange features type safety and implicit parallelism (i.e. code runs in parallel w/o any action requested to the user): TDataFrame.
root.cern.ch/doc/master/classRO … Frame.html
Perhaps this can be a complement to TTree::Draw for your usecase.

Cheers,
Danilo

Hi Danilo,

the TDataFrame looks promising, indeed. It also looks much more like modern C++ish than the old version. I am a bit reluctant to use experimental features though because all interface changes cause a lot of extra work for me.

When you run into this problem with tree->Draw or tree->Scan, you see the results immediately, i.e. it’s probably not such a big problem. However I ran into this bug with TMVA’s AddVariable function… And the problem became visible only after several hours of training.

(and thanks for including my patches!)

Hi Wolf,

I actually did not realise it was you here too :slight_smile:
I understand your concerns about experimental features. On the other hand you may choose to believe when I say that crafting the interface costed quite some effort and we’ll not change it entirely overnight unless a very serious reason forces us to do so…

Cheers,
D