Function inside Function when Fitting - Error!

Dear ROOT-community,

I’m having a “simple” fitting problem. I want to calculate the transmission of a filter consisting of 2 components (through which passes electromagnetic radiation)

The formula is

Transmission = A * exp ( - “thickness filter 1” / “abs. coeff filter 1” - “thickness filter 2” / “abs. coeff filter 2” ).

My “x” value here is the wavelength, so I should write “abs. coeff filter 1/2 (wavelength)”. I implemented the code as follows


//linear interpolation method
double ret_interp(double xx, vector<double>& v_lam, vector<double>& v_Att){

//v_lam is a vector w. wavelengths stored
//v_Att is a vector w. attenuation coefficients stored

  const Int_t ni=v_lam.size();
  double x1=0,x2=0,y1=0,y2=0;
  for(int i=0;i<ni-1;i++){
	if (  xx>=v_lam[i] && xx<=v_lam[i+1]){	
			x1=v_lam[i];
			x2=v_lam[i+1];
			y1=v_Att[i];
			y2=v_Att[i+1];
			break;	}
	else if(xx < v_lam[0]){x1=v_lam[0];x2=v_lam[1]; y1=v_Att[0];y2=v_Att[1];}
	else if(xx > v_lam[ni-1]){x1=v_lam[ni-2];x2=v_lam[ni-1]; y1=v_Att[ni-2];y2=v_Att[ni-1];}
  }
double m=(y2-y1)/(x2-x1);
double c=y1-m*x1;
  
return m*xx+c;
}

Double_t Expon(Double_t *x, Double_t *par){
return (par[0]/ret_interp(x[0],v_l_C,v_A_C)) + (par[1]/ret_interp(x[0],v_l_Al,v_A_Al));
}
Double_t fitTrans(Double_t *x, Double_t *par){
return par[0]*TMath::Exp(-Expon(x,&par[1]));
}

int main(){

vector<double> trans_norm=calc_Trans(100,300,v_A_C,v_A_Al);//%calc_Trans is a function which fills 2 vectors
TCanvas* c1 = new TCanvas("c1","c1",900,700);
TGraph* gr1 = new TGraph(v_l_C.size(),&v_l_C[0],&trans_norm[0]);
gr1->GetYaxis()->SetTitle("T");  
gr1->GetXaxis()->SetTitle("#lambda / nm");  
gr1->Draw("AP");



TF1* fit_tr = new TF1("fit_tr",fitTrans,35,40,3);
fit_tr->SetParNames("T_{G}","d_{C} [nm]","d_{Al} [nm]");
fit_tr->SetParameter(0,0.6); //transmission grating
fit_tr->SetParameter(1,100); //thickness C in nm
fit_tr->FixParameter(2,300); //thickness Al in nm

gr1->Fit(fit_tr,"R+"); //<-- doesn't work
fit_tr->Draw("SAMES");
gPad->Update();

}

I’m not getting any error messages, the fit output is:

**************************************** Minimizer is Minuit / Migrad Chi2 = 1.79769e+308 NDf = 3 NCalls = 102 T_{G} = 0.6 +/- 1.#QNAN d_{C} [nm] = 100 +/- 1.#QNAN d_{Al} [nm] = 300 (fixed)

Can anyone help me out here? Is it a problem, when defining a fit function the way I did:

T(lambda)=A*exp( - “thickness 1” / “abs. coeff 1(lambda)” - “thickness 2” / “abs. coeff 2(lambda)”).

From the fit I only want to determine A and “thickness 1”.

Thanks & cheers,
Robert

“1.79769e+308” is the “maximum possible double value”.
"#QNAN" is the “Quiet Not-A-Number”.
I guess your function performs some “invalid operations” (e.g. division by zero or the argument of “exp” is too big, and so on).

Hi Wile,

doing

Double_t param[3]={0.6,100,300};
Double_t arg[1]={<inserting any value in fit range>};

cout << fitTrans(arg,param) << endl;

gives good results. Just the fit won’t work. Is there a way to debug the fitting procedure or check where the fit goes wrong?

Cheers,
Robert

Try to TF1::SetParLimits

Hi,

setting the parameter limits gives:

If I set the parameter limits to a larger interval, the error disappears, the fit however doesn’t converge. It’s the same thing as before.

Cheers

Hi ,

You should set limits which contain the current parameter value. Before calling
TF1::SetParLimits(ipar, xmin,xmax), do TF1::SetParameter(ipar, (xmax+xmin)/2);

This is done automatically if you use version 6 of ROOT

Cheers

Lorenzo

Hi,

I might have solved it. The interpolation function doesn’t work. I tried something different, which works for now. This issue can be marked as solved.

Thanks & cheers,
Robert