Search code examples
python-3.xscipyscipy-optimize

scipy.optimize.curve_fit with conditions


I'm using the Python + NumPy + SciPy to determine the coefficients of the equation based on data. The equation is defined as follows:

def func (x, a,b,c,d):
    if x < d:
        return 0
    else:
        return a * ( 1 - np.exp( - b * (x - c) ** d)

From what I've found the traditional representation of function will not work according to this discussion and must be replaced by :

def func (x, a,b,c,d):
    return np.where ( x < c,
        0 ,
        a * ( 1 - np.exp( - b * (x - c) ** d) )
    )

This one raises the error RuntimeWarning: invalid value encountered in power a * ( 1 - np.exp( - b * (x - c) ** d).

From what I understand it happens because of an attempt to create 2 arrays of numbers (in this case):

  • the first one filled with 0
  • the second one filled with results of a * ( 1 - np.exp( - b * (x - c) ** d) )

And then, create the resulting array based on the conditional selection of those two. Creation of the second array in interval x < c in some combination with fractional values of d results in taking roots from negative numbers. And this causes the problem.

My workaround for this is:

def func (x, a,b,c,d):
    return np.where ( x < c,
        0 ,
        a * ( 1 - np.exp( - b * np.abs( x - c) ** d) )
    )

It works fine, since the range of values where x < c is defined by condition, but is there a better way to do it?

Ideally, which even prevents the calculation a * ( 1 - np.exp( - b * (x - c) ** d) if x < c and unversal, make is aplicable for larger number of conditions?


Solution

  • This solves the problem completely: https://docs.scipy.org/doc/numpy/reference/generated/numpy.piecewise.html