Ciao,
reading again your answer I would like to clarify what I’m doing because I think there will be still another complication…
You mentioned about the possibility of a new interface allowing to pass a list of parameters (names or indices). I’m afraid this is not enough…
In your combined fit example you assume 6 parameters, shared between two distributions and one (the B) is using just two parameters, while the other (the S+B) is using five parameters, with one in common…
In my case instead I have 7 parameters and one component is using all of them while the other is using 5 parameters coming from the combination of the previous 7. And in facts my struct is this:
struct GlobalChi2 {
GlobalChi2( ROOT::Math::IMultiGenFunction & f1,
ROOT::Math::IMultiGenFunction & f2) :
fChi2_1(&f1), fChi2_2(&f2) {}
double operator() (const double *par) const {
double p0[7];//flux
p0[0] = par[0];//Cele
p0[1] = par[1];//gele
p0[2] = par[2];//Cs
p0[3] = par[3];//gs
p0[4] = par[4];//1.0/Es
p0[5] = par[5];//Cpos
p0[6] = par[6];//gpos
double p1[5];//frac
p1[0] = par[1]-par[6];//gele-gpos
p1[1] = par[1]-par[3];//gele-gs
p1[2] = par[5]/par[0];//Cpos/Cele
p1[3] = par[2]/par[0];//Cs/Cele
p1[4] = par[4];//1.0/Es
return (*fChi2_1)(p0) + (*fChi2_2)(p1);
}
const ROOT::Math::IMultiGenFunction * fChi2_1;
const ROOT::Math::IMultiGenFunction * fChi2_2;
};
and while to “draw” the TF1 model correctly for the 7-parameters component was enough to do:
int ppp[7] = {0, 1, 2, 3, 4, 5, 6};
func->SetFitResult(result, ppp);
for the 5-parameters one I had to “replicate” by hand the SetFitResult method computing the errors by hand:
if (result.IsEmpty()) {
Warning("SetFitResult","Empty Fit result - nathing is set in TF1");
return NULL;
}
if (func->GetNpar()!=5)) {
Error("SetFitResult","Invalid Fit result passed - number of parameter is %d , different than TF1::GetNpar() = %d", func->GetNpar(), result.NPar());
return NULL;
}
if (result.Chi2() > 0)
func->SetChisquare(result.Chi2());
else
func->SetChisquare(result.MinFcnValue());
func->SetNDF(result.Ndf());
// printf("---------- %f\n", (double)(result.NFreeParameters()));
func->SetNumberFitPoints(result.Ndf()+result.NFreeParameters());
double* p1;
double* errp1;
int frac_params = 5;
p1 = new double[frac_params];
p1[0] = result.Parameter(1)-result.Parameter(6);//gele-gpos
p1[1] = result.Parameter(1)-result.Parameter(3);//gele-gs
p1[2] = result.Parameter(5)/result.Parameter(0);//Cpos/Cele
p1[3] = result.Parameter(2)/result.Parameter(0);//Cs/Cele
p1[4] = result.Parameter(4);//1.0/Es
errp1 = new double[frac_params];
errp1[0] = sqrt(pow(result.ParError(1), 2) + pow(result.ParError(6), 2));//gele-gpos
errp1[1] = sqrt(pow(result.ParError(1), 2) + pow(result.ParError(3), 2));//gele-gs
errp1[2] = p1[2]*sqrt(pow(result.ParError(5)/result.Parameter(5), 2) + pow(result.ParError(0)/result.Parameter(0), 2));//Cpos/Cele
errp1[3] = p1[3]*sqrt(pow(result.ParError(2)/result.Parameter(2), 2) + pow(result.ParError(0)/result.Parameter(0), 2));//Cs/Cele
errp1[4] = result.ParError(4);//1.0/Es
for (int ii=0; ii<frac_params; ii++) {
func->SetParameter(ii, p1[ii]);
func->SetParError(ii, errp1[ii]);
}
since I didn’t find the way to pass to SetFitResults the ‘combinations’ of parameters I needed…
So in somehow I would have need the possibility to pass strings of parameters that should be interpreted not only as the names of the parameters but should be parsed as formulas… I imagine this is not so straightforward…
Thanks again,
Matteo
Matteo