Conditional variables in fit functions

I am attempting a piece wise linear regression using a conditional statement in my fit function. The break point between to the 2 functions does not to change from my initial guess. Below is the auto-generated procedure. Can you provide some guidance about how to do a piece wise linear regression and why the break point is not being estimated? That is w[4] aka breakX. Thanks.

Function TwoSegment(w,x) : FitFunc
    Wave w
    Variable x
 
    //CurveFitDialog/ These comments were created by the Curve Fitting dialog. Altering them will
    //CurveFitDialog/ make the function less convenient to work with in the Curve Fitting dialog.
    //CurveFitDialog/ Equation:
    //CurveFitDialog/ variable result
    //CurveFitDialog/ if (x < breakX)
    //CurveFitDialog/   result = a1 + b1*x
    //CurveFitDialog/ else
    //CurveFitDialog/   result = a2 + b2*x
    //CurveFitDialog/ endif
    //CurveFitDialog/ f(x) = result
    //CurveFitDialog/ End of Equation
    //CurveFitDialog/ Independent Variables 1
    //CurveFitDialog/ x
    //CurveFitDialog/ Coefficients 5
    //CurveFitDialog/ w[0] = a1
    //CurveFitDialog/ w[1] = b1
    //CurveFitDialog/ w[2] = a2
    //CurveFitDialog/ w[3] = b2
    //CurveFitDialog/ w[4] = breakX
 
    variable result
    if (x < w[4])
        result = w[0] + w[1]*x
    else
        result = w[2] + w[3]*x
    endif
    return result
End
It is actually very difficult to make the break point a fit coefficient. If you think about it, as the break point varies within the space between two points, changes make only a small change to the chi-square value (the measure of goodness of fit). But if the coefficient value crosses the position of one of your data points, it potentially makes a big difference.

In general, you need an epsilon wave with the epsilon for the break point set pretty large. If you are using Igor 7, you can read about the epsilon wave here:

DisplayHelpTopic "The Epsilon Wave"

Otherwise...

Curve fitting uses partial derivatives of your fit function with respect to the fit coefficients in order to find the gradient of the chi-square surface. It then solves a linearized estimate of the chi-square surface to find the next estimate of the solution (the minimum in the chi-square surface).
Since Igor doesn't know the mathematical equation for your fit function, it must approximate derivatives numerically using finite differences. That is, a model value is calculated at the present estimate of the fit coefficients, then each coefficient is perturbed by a small amount, and the derivative is calculated from the difference. This small perturbation, which is different for each coefficient, is called "epsilon".
You can specify the epsilon value for each coefficient by providing an epsilon wave to the CurveFit or FuncFit operations using the /E flag. If you do not provide an epsilon wave, Igor determines epsilon for each coefficient using these rules:
If the coefficient wave is single precision (not recommended):
if coef[i] == 0
eps[i] = 1e-4
else
eps[i] = 1e-4*coef[i]
If the coefficient wave is double precision:
if coef[i] == 0
eps[i] = 1e-10
else
eps[i] = 1e-10*coef[i]
In the Curve Fitting dialog, when you are using a user-defined fitting function, you can select an epsilon wave from the Epsilon Wave menu. When you select _New Wave_, or if you select an existing wave from the menu, Igor adds a column to the Coefficients list where you can edit the epsilon values.
There are a couple of reasons for explicitly setting epsilon. One is if your fit function is insensitive to a coefficient. That is, perturbing the coefficient makes a very small change in the model value. Sometimes the dependence of the model is so small that floating-point truncation results in no change in the model value. You have to set epsilon to a sufficiently large value that the model actually changes when the perturbation is applied.
You also need to set epsilon is when the model is discrete or noisy. This can happen if the model involves a table look-up or a series solution of some sort. In the case of table look-up, epsilon needs to be large enough to make sure that you get two distinct values out of the table.
In the case of a series solution, you have to stop summing terms in the series at some point. If the truncation of the series results in less than full floating-point resolution of the series, you need to make sure epsilon is large enough that the change in the model is larger than the resolution of the series. A series might include something like a numerical solution of an ODE, using the IntegrateODE operation. It could also involve FindRoots or Optimize, each of which gives you an approximate result. Since these operations run faster if you don't demand high precision, there may be a strong incentive to decrease the accuracy of the computation, and that may in turn lead to a need for an epsilon wave.

I would set the epsilon for w[4] to a substantial fraction of the distance between data points.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com