C/C++ functions exposed to TFormula and TTreeFormula?

I was wondering how TFormula and TTreeFormula know about TMath::Sin and the like - and if it was possible to add my own C++ functions.

i.e:

[code]namespace MyNamespace {
Double_t XReturner( Double_t x ) { return x; }
};

myTree->Draw(“MyNamespace::XReturner( myX )”);
[/code]

Is such a thing possible/supported? Or are the TMath (and the like) functions exposed to TTreeFormula by way of internal voodoo magic?

Regards,

  • Peter

Hi Peter,

[quote] and if it was possible to add my own C++ functions. [/quote]Yes :slight_smile:
This is one of the fundamental feature of ROOT, via the generation of dictionaries, ROOT can provide access to (almost) all C++ classes and function to an interpreter (CINT, pyroot, TTreeFormula).

The simpliest way of generating a dictionary (see User’s Guide for more complex example) is to use ACLiC. For example with a file myfunc.C simply do:root [] .L myfunc.C+orgROOT->ProcessLine(".L myfunc.C+") or if you function already exist in a shared library and you have an header file (myfunc.h) do:root [] gSystem->Load("mylib.so"); root [] .L myfunc.h+orgROOT->ProcessLine(".L myfunc.h+")

Cheers,
Philippe.

// file myfunc.C #include "TObject.h" namespace MyNamespace { Double_t XReturner( Double_t x ) { return x; } };

Hmm, what I wanted this for was to apply a weight to a variable which is described in a histogram.

I have some simple code:

[code]#include <TH1F.h>

TH1F *histToWeight = NULL;

#include
using namespace std;

void SetWeightHist( TH1F *weightHist )
{
histToWeight = weightHist;
}

Double_t GetHistWeight( Double_t value )
{
return histToWeight->GetBinContent( histToWeight->FindBin( value ) );
}[/code]

My idea was to do:

SetHistWeight( someFile->Get("MyWeightHist") ); tree->Draw("variable", "GetHistWeight( variable )");

The problem is, even if I make GetHistWeight do nothing (return 1), it is horrendously slow. So I have given up on this idea and instead loop over the events myself - it runs many thousands of times faster. I suppose this is intrinsic ? Is there any good way to do this?

Hi,

Yes calling function in TTree::Draw is somewhat slow (it goes through the interpreter).

Alternatively you use MakeProxy as follow (with the files below the signature):ntuple->Draw("wrapper.C+","","nohist");

Cheers,
Philippe

[code]// File wrapper.h
#include <TH1F.h>

TH1F *histToWeight = NULL;

#include
using namespace std;

void SetWeightHist( TH1F *weightHist )
{
histToWeight = weightHist;
}

Double_t GetHistWeight( Double_t value )
{
return histToWeight->GetBinContent( histToWeight->FindBin( value ) );
}[/code]

// File wrapper.C void wrapper() { double weight = GetHistWeight( variable ); if (weight) { htemp->Fill( variable, weight ); } }

So I find myself wanting to do something similar, this time to Draw() something which is evaluated in C, but I find this interpreting stuff too slow.

I came across the sort of thing I was looking for:

root.cern.ch/root/html/TFormulaPrimitive.html

In particular:

     TFormulaPrimitive::AddFormula(new TFormulaPrimitive("Pow2","Pow2",TFastFun::Pow2));
      TF1 f1("f1","Pow2(x)");

This is exactly what I was looking for - but does it work with TTreeFormulae? I’m not having much luck…

Hi,

TTreeFormula has not (yet) been upgraded to taken advantage of the better formula compilation implemented for TFormula (and using TFormulaPrimitive).
However TTreeFormula can directly call any static or global function (i.e For example TFastFun::Pow2). i.e. you can do:tree->Draw("TFastFun::Pow2(myvar)");

Cheers,
Philippe.

This is extremely slow. Is there any other way short of calling it myself? I’d really like to use a TTreeFormula, it would be so convenient. In particular I want to compile functions in C++ which are generated at runtime, and then evaluate them as part of a TTreeFormula expression.

As a basic example, something that takes ~5 seconds to do in a TTree::Draw() expression for ~5 million events takes >140 seconds when done in a TTree::Draw(“MyExternalFunction(a,b)”).

Hi,

Yes calling function in TTreeFormula is somewhat slow (it goes through the interpreter).

To avoid this slow down, currently, you must use MakeProxy as described earlier in this post.

Cheers,
Philippe