Adding functionality to TFormula

Hello again,

I am trying to write a new class inheriting from TFormula in order to be able to
parse and evaluate expressions which include a set of named parameters
corresponding to acquisition data which I can handle, e.g. if I had an expression
"CI_0221_GG > 3145", in my ‘KVFormula’ class I want to do something like
(where expr = “CI_0221_GG”, i.e. the part that TFormula doesn’t understand, corresponding to my data parameters)

if ( gMultiDetArray->GetACQParams()->FindObject( expr )){
//unknown symbol corresponds to acquisition parameter
Float_t data = gMultiDetArray->GetACQParam( expr )->GetValue()
//substitute value ‘data’ into expression

}

In my class I have followed the instructions for overriding the TFormula(name,title) ctor - I copied it in my class, making it call the TFormula() default ctor - and then I redefined the DefinedVariable, DefinedValue and DefinedString methods. Only DefinedVariable seems to be invoked by Analyze(). However I can’t figure out how to substitute the value I want into the expression…

I did this:
Int_t KVFormula::DefinedVariable(TString &chaine,Int_t &action)
{
cout << “DefinedVariable called for : " << chaine.Data() << endl;
Int_t dv = TFormula::DefinedVariable(chaine,action);
cout < result is " << dv << “, action=” << action << endl;
if( chaine == “CI_0221_GG” ){
Int_t data=15;
//chaine.Form(”%d",acqpar);
action = kDefinedVariable;
dv = acqpar;
}
return dv;
}

and tried action = kConstant, kVariable, etc… I tried returning the action code, returning the data, writing the data in the string, etc. etc. My parameter is always evaluated as if it equals zero! Can somebody please help ?

Thanks a lot
John

Hi John,

It would be good if you could post a short/running version of your code.
May be you can get some inspiration from one of the Roofit classes RooFormula.
See:
root.cern.ch/root/htmldoc/RooFormula.html
root.cern.ch/root/htmldoc/src/Ro … tml#DsUKlC

Rene

Bonjour René

Here is my class KVFormula, and here is a sample session (using ROOT v5.13/05 compiled from CVS on 2/11/2006):

root [0] .L KVFormula.cpp+
root [2] KVFormula r(“r”,“CI_0221_GG3x”)
DefinedVariable called for : CI_0221_GG
—> result is -1, action=144
DefinedVariable called for : x
—> result is 0, action=144
root [3] r.GetExpFormula()
(class TString)“15*(3*x)”
root [4] r.Eval(1)
(const Double_t)0.00000000000000000e+00

I’ll look at the Roofit classes. Thanks a lot
John
KVFormula.h (668 Bytes)
KVFormula.cpp (3.77 KB)

Hi,

Without testing it, it looks like you should do:

Int_t KVFormula::DefinedVariable(TString &chaine,Int_t &action) { cout << "DefinedVariable called for : " << chaine.Data() << endl; Int_t dv; if( chaine == "CI_0221_GG" ){ Int_t data=15; //chaine.Form("%d",acqpar); action = kDefinedVariable; dv = acqpar; } else { dv = TFormula::DefinedVariable(chaine,action); } cout <<DefinedVariable> result is " << dv << ", action=" << action << endl; return dv; }

Cheers,
Philippe

Hi Philippe,

I did as you suggest, and now I get the following:

root [7] KVFormula g(“g”,“CI_0221_GG*x”)
DefinedVariable called for : CI_0221_GG
DefinedVariable> result is 15, action=150
DefinedVariable called for : x
DefinedVariable> result is 0, action=144
root [8] g.Eval(1)
DefinedValue called for code=0
DefinedValue called for code=1
(const Double_t)4.37684320020684364e-287

I guess the call to DefinedValue with code 0 is for ‘x’ (?)
But then if the call with code 1 is for my ‘CI_0221_GG’ variable, how do I know what value to return ?

John

Hi John,

Can you send me a running version of your current code?

Thanks,
Philippe

Thanks for the reply,
The code is attached.
Cheers
John
KVFormula.cpp (4.14 KB)
KVFormula.h (668 Bytes)

Hi John,

In DefinedValue you need to return the correct value (instead of calling the ‘empty’ TFormula::DefinedValue.

For example:[code]Int_t KVFormula::DefinedVariable(TString &chaine,Int_t &action)
{
// cout << “DefinedVariable called for : " << chaine.Data() << endl;
// Int_t dv = TFormula::DefinedVariable(chaine,action);
// cout << " —> result is " << dv << “, action=” << action << endl;
// if( chaine == “CI_0221_GG” ){
// Int_t data=15;
// chaine.Form(”%d",data);
// action = kConstant;
// dv = data;
// }
// return dv;
cout << “DefinedVariable called for : " << chaine.Data() << endl;
Int_t dv;
if( chaine == “CI_0221_GG” ){
Int_t data=15;
//chaine.Form(”%d",acqpar);
action = kDefinedVariable;

dv = fNval;

} else {
dv = TFormula::DefinedVariable(chaine,action);
}
cout <<"DefinedVariable> result is " << dv << “, action=” << action << endl;
return dv;
}

Double_t KVFormula::DefinedValue(Int_t i)
{
cout << “DefinedValue called for code=”<< i<< endl;
if (GetAction(i)==kDefinedVariable) {
return 15;
}
return 0;
}[/code]
Where, of course :wink:, you need to replace “return 15;” by something a bit smarter!

Cheers,
Philippe.