2 or more fittings in the same graph
mssmtrainee
I wonder if Igor has a simple way to do multiple fittings with different ranges. I tried:
CurveFit/N line, w1[ start_of_range1, end_of_range1] /X=w0 /D
CurveFit/N poly 3, w1[ start_of_range2, end_of_range2] /X=w0 /D
But this method does not work for a simple reason: as soon as the second fitting is made, the window is updated and the first fitting is gone. Then I tried to use a user defined function where w[0]=start_of_range1, w[1]=end_of_range1, w[7]=start_of_range2, w[8]=end_of_range2:
Function PieceWiseFit(w,x)
Wave w
Variable x
Variable result
if(x>w[0] && x<w[1])
result = w[2] + w[3]*x
elseif(x>=w[7] && x<w[8])
result = w[4] + w[5]*x +w[6]*x^2
endif
return result
End
No luck either! Any help will be appreciated. Thanks! (Sorry I don't know how to convert some parts of the post back to normal, so it's all in Igor)
The solution is to re-name to first fit wave before doing the second fit.
Your piece-wise fit function will most likely fail while trying to adjust the coefficients w[0], w[1], w[7], and w[8]. It might work if you hold those coefficients while fitting. I expect that's what you want anyway- it sounds like you just want two line fits over specific ranges.
Simply re-naming the fit curve wave is the best way to proceed.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
March 22, 2012 at 09:33 am - Permalink
So, the second fit-wave overwrites the first; but the residual of the second fit-wave does not??? Instead, Res_ keeps history of the fittings. I'm confused... Residual is the difference between the data and the model (the fit); so it should related to my fit. If my new fit overwrites the old fit, then the residual should also overwrite the old residual. But that is not what is happening here; while my most update fit is in a small range (in blue); my most update residuals wave takes the old fitting range into consideration (see picture).
Basically, I just want to do multiple fittings using for loop and would like to sum the residuals for EACH independent fitting; unfortunately the residuals keep historical fittings and keep adding up.
March 23, 2012 at 11:38 am - Permalink
Residuals do overwrite- if your two fits overlapped, you would find that the part of the second fit that overlapped the first was overwritten.
To do what you're describing, you can use an explicit residual wave and initialize it to zero before doing the fit. Something like:
Wave YData
Duplicate/O YData, Resid1
Resid1 = 0 // pre-fill residual with zeroes
CurveFit ... YData[p1, p2] /R=Resid1
Variable sumResids = sum(Resid1)
Resid1 = 0 // re-initialize residual
CurveFit ... YData[p1, p2] /R=Resid1
sumResids += sum(Resid1)
...
end
Naturally, this won't compile or run...
In fact, if you want you can do this with the destination (model curve) wave as well. Using an explicit destination wave, though, gives you point-by-point model values instead of the evenly-space smooth curve.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
March 23, 2012 at 02:33 pm - Permalink
One last thing concerning the fit; if you look at the attached picture you see two fits which are the best fits in their respective ranges. However I would like continuity in these fittings, meaning I'd like the last point (line3-Initial guess) of the linear fit to "match" the first point of the polynomial fit. Other words, the linear fit will constraint to pass by a specific point; I understand there will be a catch: the error of the linear fit will be bigger. But I need to ignore the mathematical error and take the physical issues of the experiment into consideration. Thanks!
March 27, 2012 at 09:09 am - Permalink
You will need to do some algebra to figure out how to make the line and polynomial pass through a common point at the breakpoint.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
March 27, 2012 at 09:35 am - Permalink
Two more little questions:
1- I got an error while running the code (see the code, graph and error tab in the picture); any thoughts?
2- A different topic: when I have a wave(or an array of number) ; is there a command/way to identify the minimum value in the wave and print the index of the minimum value? (Or do I have to write a whole loop? but this sounds like I need a bomb to kill mosquito)
Again, thank you! I really appreciate the kind assistance.
Cheers,
March 28, 2012 at 12:57 pm - Permalink
do
indx+=1
while(myWave[indx] != WaveMin(MyWave))
print indx // this will print the index of the minimum value of MyWave
March 28, 2012 at 01:21 pm - Permalink
How about
Print V_minRowLoc
I'm assuming that MyWave is 1D.
March 29, 2012 at 01:47 am - Permalink
Usually the error means what it says – the fit function calculated NaN at some stage, which normally means that it did something illegal such as 1 / 0 or sqrt(-1) (Igor doesn't auto-promote to complex). Offhand I don't really see what the problem is.
Note that your fit functions are problematic as the parameters are not independent. For example, your force_line function:
w[0] (x - w[1]) + w[2]
is naturally identical to
w[0] x - w[0] w[1] + w[2].
This is problematic because for any non-zero w[0] a change in w[1] can be compensated by an appropriate change in w[2]. An alternative way of formulating this is that there is no unique solution for w[1] and w[2].
I'd normally expect lots of 'singular matrix' errors, but that's not happening because you're holding w[1] and w[2] constant. So it is not a problem for this particular fit but it is something to keep in mind.
March 29, 2012 at 07:39 am - Permalink
He did this based on advice from WaveMetrics tech support...
You're right about the linear dependence problem, but a key part of the advice from tech support was to hold w[1] and w[2]. This is the easiest way to transmit constants to a fit function. The particular format he used is a natural way to write a line in point-slope format. In this format, w[1] and w[2] are the coordinates of point through which the line must pass.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
March 29, 2012 at 09:30 am - Permalink
741 is again correct (he's a very smart fellow- we know him :) in that it usually is exactly what it says- your fit function got a result of NaN (or Inf) and returned it as one of the values of the model. Again, your fit functions don't seem like they would generate such an error. Is it possible that you are passing in a bad value in your coefficient wave initial guesses? You can put in debugging code in your fit function to detect when that might happen. It could look something like this:
Wave w
Variable x
Variable result = w[0]*(x-w[1]) + w[2]
if (NumType(result))
print "Bad fit function result: ", result, x, w
endif
return result
end
Naturally, you will want to remove that once you figure out what the problem is.
John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
March 29, 2012 at 09:39 am - Permalink