Search code examples
pythonscipycurve-fitting

Curve fitting with three unknowns Python


I have a data set where from one x I can obtain the exponential function f(x) = a*np.exp(-b*(x-c)) , defined in Python like this:

def func(x, a, b, c): 
    return a*np.exp(-b*(x-c))

f = func(x, a, b, c)

a = 1.6
b = 0.02

a, b, c are all known in this case.

However, after an algebraic solution, where I need to partition this function to three different members, I need to obtain a solution for this function:

g(x) = f1*a1*np.exp(-b1*(x-c)) + f2*a2*np.exp(-b2*(x-c)) + f3*a3*np.exp(-b3*(x-c)).

a1, a2, a3, f1, f2, f3 and c are all known, what I need to do is to fit g(x) to f(x) in such way to obtain b1, b2 and b3, using curve_fit or any kind of adequate fit for this kind of problem.

f1, f2, f3 represent fractions and their sum is equal to 1.

My question is: how do I define the g(x) function in order to obtain a solution for b1, b2 and b3?

For clarity and testing purposes, I attach also possible values to tackle this problem, but note that f1, f2, f3 and a1, a2, a3 should be part of inputs as they change from one point to another. I have an array, but am simplifying the calculation in order to make it clear what to obtain:

x = np.arange(300., 701., 5.)

f1=0.3
f2=0.5
f3=0.2

c = 350.

a1=1.82
a2=7.32
a3=1.52


Solution

  • Starting from the scipy curve fit example (https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html), then simply make b1, b2, b3 the unknown inputs to curve fit with all other variables defined outside. Here, I assume you meant fit g(x) to f(x)...

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.optimize import curve_fit
    
    f1=0.3
    f2=0.5
    f3=0.2
    
    c = 350.
    
    a1=1.82
    a2=7.32
    a3=1.52
    
    def func(x, a, b, c): 
        return a*np.exp(-b*(x-c))
    
    def func2(x, b1, b2, b3):
        return f1*a1*np.exp(-b1*(x-c)) + f2*a2*np.exp(-b2*(x-c)) + f3*a3*np.exp(-b3*(x-c))
    
    #You need to define some a and b values 
    a = 1
    b = 2
    x = np.arange(300., 701., 5.)
    popt, pcov = curve_fit(func2, x, func(x, a, b, c))