Check the status of a TTreeFormula

Hi,

I was wondering if there is a way to check the status of a TTreeFormula object ?

My problem is that I have a vector<TTreeFormula*> with one element being not properly initialized (i.e. yielding an “Error in TTreeFormula::Compile: Bad numerical expression” upon construction). My code then yields a segmentation violation when applying TTreeFromula::EvalInstance() on the problematic item.

I found the occurrence of ‘Bad numerical expression’ in TTreeFormula.cxx but I was unable to find how to easily determine if my TTreeFormula object is in a valid (i.e. ready to use) state.

Usually these issues are handled with exceptions (guaranteeing that allocated memory is being properly freed) but I understand this might not be an option for ROOT.

Thanks a lot.

Cheers,
Karolos

After some investigation, I figured that checking the return string of TreeFormula::GetTitle() against “” SEEMS to do what I want (i.e. detect improper initialization of the formula expression). Is this a feature ?

My segmentation fault seems to be due to an improper update of the internal tree of the formula, which I understand is impossible to protect against, except checking in ROOT’s internals of the TTree is still “registered”.

Cheers,
Karolos

Hi,

The way to check whether a TTreeFormula is valid or not is to check that GetNdim is not zero.

What do you mean by ‘improper’? (If it is really ‘improper’ shouldn’t it be prevent at the source?)
If you TTree is actually a TChain, every time the TChain moves from one File/Tree to the other, you need to call TTreeFormula::UpdateFormulaLeaves().

Cheers,
Philippe.

Hi Philippe,

Thanks for your reply. I’ll use GetNdim().

My case arises from the fact that I cannot use a TChain or PROOF because I don’t know a priori the file: my code scans a directory for the presence of a ROOT file, and processes it. An error in my code yielded the TTreeFormulat:SetTree()/TTree:UpdateFormulaLeaves() called at a wrong moment [some chain of events being triggered in the background], yielding a segmentation violation when using EvalInstance(). I don’t know if PROOF has a way to accomodate my case: I only know of the case where one TChain defined at the beginning of the job is accessed on several nodes, but not that of a “directory checking”.

The only thing I can think of to prevent this is that ROOT could check the list of open files and then check if a TTree is still active at the address the TTreeFormula has stored. But it’s very weak, except if the TTree() destructor or TFile::Close() “de-registers” from the internals of ROOT every time, and if that’s somehow guaranteed.

Otherwise, I’ve thought about a IsValid() function for TTreeFormula which would return false in case of a non properly initialized formula. This would include a test for GetNdim() but would also check if some offset from the memory location pointed to as being a TTree has some “magic number” that every TTree should possess, hence preventing a segmentation violation. But this is tricky since it would also require checking that the memory location still belongs to the thread/process. But in my opinion, this is not in the scope of ROOT. Correct me if you think I’m wrong. Checking against the known internals would be already good enough.

Again, this issue is not really a concern since the initial error was mine, but I appreciate your concern of trying to prevent it at the source somehow. This is something very important in using ROOT in a fault-tolerant environment, where segmentation violations are a killer.

Cheers,
Karolos

[quote]The only thing I can think of to prevent this is that ROOT could check the list of open files and then check if a TTree is still active at the address the TTreeFormula has stored.[/quote]TTreeFormula is supposed to be a very fast (especially EvalInstance) and I would rather reduce the number of things to check rather than increase it. In the current design/implementation it is up to the user to insure that the TTreeFormula’s TTree is correctly managed (i.e. SetTree/UpdateFormulaLeaves called at the right time) and it is an error otherwise. If your application can afford the extra check, you can wrap the call to EvalInstance with a routine containing the check you mentioned (i.e. check NDim and check that the TTree and/or its file is still open).

Cheers,
Philippe.

Hi Philippe,

Indeed, I totally agree with you: this check should NOT be performed in EvalInstance() but instead using something prior to the loop. Now that I have Ndim(), I’m OK.

I have a more technical question. What’s the performance of TTreeFormula compared to other methods ?

  1. TBranch::GetLeaf()->SetAddress(ptr); vs. *ptr = TTreeFormula::EvalInstance(); where the leaf is BRANCHNAME.leafname (i.e. no operations involved);

  2. *ptr = TTreeFormula::EvalInstance(); vs. *ptr = MySelector::myOwnFunction(); (MySelector derives from TSelector, which has access to the variables defined in TSelector::Init() using TLeaf::SetAddress())

I haven’t done a full benchmark but maybe the ROOTteam has. Basically I wonder what’s the level of optimizaion behind a TTreeFormula. I wonder especially because I can compile my application using O3 and it’s tougher to do the same for the default ROOT install on worker nodes.

Thanks,
Karolos

Hi,

Compare to a well formed implementation of 1) or 2), TTreeFormula will be slower as it need to execute a sort of preparsed bytecode. What TTreeFormula gives you is the automatic discovery and attachment of the branch/leaf and the automatic limitation to reading only the required branches. Both are also done automatically when using the result of MakeProxy as the basis for your Selector. In the end, both TTreeFormula and MakeProxy are coding-time saver but can always be improved upon by hand coding the same operation (and thus being able to skip the extra layer of indirection and testing that comes with Generality).

Cheers,
Philippe.

Hi,

I’m trying to implement a loop over a TChain with a TTreeFormula based selection. I’m having problems when I add more than one file to the TChain.

And I understand from previous comments that I need to call TTreeFormula::UpdateFormulaLeaves(), every time the file in TChain changes. But how can I detect that a file change has occurred?

I tried with GetNdim(), but this function is always returning 1.

Thanks in advance,
Miguel

Hi Miguel,

you can either register an object to the be Notify-ed by the TChain (like TSelector does) or you can monitor the value of chain->GetTreeNumber() after executing the chain->LoadTree(…)

Cheers,
Philippe.