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 ?
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)
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 ?
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 , you need to replace “return 15;” by something a bit smarter!