2 or more fittings in the same graph

Hi all,
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 automatically-created fit curve is created using a wave named by prepending "fit_" to the beginning of the name of the Y data wave. So if you do two fits to the same wave, but over different ranges, the second wave overwrites the first.

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
johnweeks wrote:
the second wave overwrites the first


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.
test0000.JPG (249.83 KB)
Residuals are somewhat different: they have to be point-by-point, that is, each data point in your fit gets one residual point. But the fit curve uses 200 evenly-spaced points so that you get a smooth fit curve. Consequently, the fit curve overwrites itself, where the residual curve just makes a wave with the same number of points as the input data.

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:
Function doMyfits(YData)
    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
Perfect, thanks!
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!
Igor_Forum00.JPG (43.68 KB)
OK- for that you really will need to write the fit function as one single function with the breakpoint as a parameter. It just takes one parameter specifying the X value where the break occurs. It would ease fitting if you were satisfied to take the breakpoint as a constant (not a fit parameter). Make it a fit coefficient, but hold the value during fitting.

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
Thank you! I think I did it (see picture).
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,
Igor_Forum01.JPG (247.55 KB)
Basically I am looking for a "magic command" to substitute this:
Variable indx=-1
do
 indx+=1
while(myWave[indx] != WaveMin(MyWave))
print indx    // this will print the index of the minimum value of MyWave
mssmtrainee wrote:
Basically I am looking for a "magic command" to substitute this:
Variable indx=-1
do
 indx+=1
while(myWave[indx] != WaveMin(MyWave))
print indx    // this will print the index of the minimum value of MyWave


How about
WaveStats /Q/M=1 MyWave
Print V_minRowLoc

I'm assuming that MyWave is 1D.
mssmtrainee wrote:
1- I got an error while running the code (see the code, graph and error tab in the picture); any thoughts?


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.
741 wrote:
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.

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
mssmtrainee wrote:
1- I got an error while running the code (see the code, graph and error tab in the picture); any thoughts?

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:
Function Force_line(w,x):FitFunc
    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