0

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

PEBKAC
  • 748
  • 1
  • 9
  • 28
  • 1
    $f_1*a_1$ is just another constant. You can fit the equation $g(x) = \alpha_1 e^(-b_1 (x-c)) + ...$ , where $\alpha = f_1 a_1$ and then apply your additional constraint to figure out $f_1$ and $a_1$ – Edgar H Feb 01 '23 at 13:17

1 Answers1

2

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))
Ed Smith
  • 12,716
  • 2
  • 43
  • 55
  • That is very helpful, thanks! The only issue I have is that I simplified the problem to one set of points, but my f1, f2, f3, a1, a2, a3 would need to be func2 inputs as they change from point to point. Any thoughts on how to incorporate them inside func2 and how would then change the curve_fit definition? Should I rewrite the question and set arrays instead of plain numbers in order to make if clearer? – PEBKAC Feb 01 '23 at 11:50
  • 1
    It's not directly possible to provide non-fitted inputs to a function in `curve fit` as far as I know, but you could wrap in a function like this question https://stackoverflow.com/questions/10250461/passing-additional-arguments-using-scipy-optimize-curve-fit or alternatively, wrap the code above inside a function e.g. `fit_points` with all arguments f1, f2, f3, a1, a2, a3 as inputs, and this calls `curve_fit` for that point and returns the `popt` values. – Ed Smith Feb 01 '23 at 14:18