1
$\begingroup$

I'm trying to fit a set of data to a non-linear model and I quickly ran into a problem where it keeps running into complex values. Here's my current code:

ag1 = 223 + 20.5/60; bg1 = 131 + 57/60; cg1 = {79 + 5/60, 75 + 42/60, 74 + 48/60, 74 + 50.5/60, 75 + 15/60, 75 + 52/60, 76 + 54/60, 77 + 40/60, 78 + 53.5/60, 80 + 3/60, 81 + 43.5/60, 83 + 14.5/60, 85 + 9.5/60}; thetag1 = {44.3042, 49.6458, 54.6708, 57.0958, 60.5625, 63.2958, 66.1958, 68.3875, 71.0125, 73.4292, 76.0792, 78.3458, 82.9625}; deltag1 = cg1 - ag1 + 200; data = Transpose[{thetag1, deltag1}]; fitfunct = theta \[Degree] + ArcSin[Sin[60 \[Degree] ]*Sqrt[(n)^2 - Sin[theta \[Degree]]^2] - Sin[theta \[Degree]]*Cos[60 \[Degree]]]/\[Degree] - 60 \[Degree]; error = StandardDeviation[{ 20, 21, 19.5, 20.5, 20.5, 21}]* Table[1, {i, 13}]; fit = NonlinearModelFit[data, {fitfunct}, n, theta, Weights -> 1/error^2] 

To which the output was

NonlinearModelFit::nrlnum: The function value {58.1404 -26.4015 I,44.1256 +0. I,28.5762 +0. I,22.9152 +0. I,15.6495 +0. I,10.2762 +0. I,<<18>> +<<1>>,0.690677 +0. I,-4.09825+0. I,-8.20392+0. I,-13.0284+0. I,-17.0034+0. I,-22.2808+0. I} is not a list of real numbers with dimensions {13} at {n} = {1.7459}. >> 

I tried to look up a solution to this and found this: How to solve this FindFit::nrlnum:

Following the advice there, I tried adding in "NormFunction -> (Norm[#, Infinity] &)" to my fit argument but that wasn't allowed with NonlinearModelFit, so I tried switching to FindFit, but FindFit wouldn't allow me to include weights!

I tried getting rid of the weights and without the weights, FindFit with "NormFunction -> (Norm[#, Infinity] &)" in it's argument was able to get me a reasonable value for n. However, I really need to be weighing my data by it's uncertainties.

Do any of you know how I can get my fit to run and accept weights simultaneously?

$\endgroup$
1
  • $\begingroup$ Well, i bet your function is false. At least for this dataset.If you look in the plots for some n's (which have to be in a narrow interval btw.) the really don't seem to fit well anyway. Try yourself: Show[Plot[Table[fitfunct,{n,Sqrt[2],Sqrt[4],(Sqrt[6]-Sqrt[1])/20}],{theta,40,90}],ListPlot[data]] $\endgroup$ Commented Sep 29, 2016 at 22:20

1 Answer 1

3
$\begingroup$

This is an extended comment to echo @JulienKluge 's comment which says your function is not a very good fit to the data.

In setting up the code I recommend first doing the fit without the weights (especially as a plot of the data does not suggest any wild (and independent) deviations and the proposed weights are identical - so why have weights in the first place?).

One needs real values for fitfunct and a contour plot of fitfunct by theta and n shows the narrow range of acceptable values for n that @JulienKluge mentioned:

fitfunct = theta ° + ArcSin[Sin[60 °]*Sqrt[(n)^2 - Sin[theta °]^2] - Sin[theta °]*Cos[60 °]]/° - 60 °; ContourPlot[fitfunct, {theta, 44, 83}, {n, 0.5, 2}, ContourLabels -> (Text[Framed[#3], {#1, #2}, Background -> White] &), PlotRange -> Full, Frame -> True, FrameLabel -> (Style[#, Large, Bold] & /@ {"theta", "n", "Contours of fitfunct"})] 

Contours of fitfunct by theta and n

We see that we need to restrict n to be between about 1 to 1.7.

fit = NonlinearModelFit[data, fitfunct && 1.2 < n < 1.7, {{n, 1.6}}, theta]; fit["BestFitParameters"] (* {n -> 1.6716614603902369`} *) 

And the starting value still needs to be pretty close the best value to run without errors or warnings. And yet the fit is extremely poor:

Manipulate[ ListPlot[{Transpose[{thetag1, deltag1}], Transpose[{thetag1, theta ° + ArcSin[Sin[60 °]*Sqrt[(n)^2 - Sin[theta °]^2] - Sin[theta °]*Cos[60 °]]/° - 60 ° /. theta -> thetag1}]}, PlotRange -> {Automatic, {-20, 85}}, PlotLegends -> {"Observed", "Predicted"}], {{n, 1.6716614603902369}, 1, 1.7, Appearance -> "Labeled"}, TrackedSymbols :> n] 

Data and fit

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.