Curve-Fitting over an integral containing both a data array and function in python

Viewed 404

I have a data set described by an integral with unknown constants that I am attempting to determine using python's curve_fit. However, the integrand contains a function being multiplied against a data set

def integrand(tm, Pm, args):
    dt, alpha1, alpha2 = args
    return Pm*(1-np.e**( -(alpha1 * (tm+dt))) )*np.e**(-(alpha2 * (tm+dt)))

Where Pm is a 1-D array of collected data of impulse responses, Image of Impulse data and Integral Curve

The orange curve represents the impulse data and the blue curve is what the integral should evaluate to

tm is the variable of integration, and dt, alpha1, alpha2 are unknown constants and the bounds of integration would be from 0 to tm.

What would be the best way to perform a curve fit on an integral of this kind, or possibly other ways to solve for the unknown constants?

The Data sets are linked here

1 Answers

From the length of the data sets, it seems that the intent is to fit integrand(t) to output(t+dt). There are several functions in the scipy optimize module that can be used to do this. For a simple example, we show an implementation using scipy.optimize.leastsqr(). For further details see the tutorial at scipy optimize

The basic scheme is to create a function that evaluates the model function over the independent coordinate and returns a numpy array containing the residuals, the difference between the model and the observations at each point. The leastsq() finds the values of a set of parameters that minimizes the sum of the squares of the residuals.

We note as a caveat that the fit can be sensitive to the initial guess. Simulated annealing is often used to find a likely global minimum and provide a rough estimate for the fit parameters before refining the fit. The values used here for the initial guess are for notional purposes only.

from scipy.optimize import leastsq
import numpy as np

# Read the data files    
Pm = np.array( [ float(v) for v in open( "impulse_data.txt", "r" ).readlines() ] )
print type(Pm), Pm.shape

tm = np.array( [ float(v) for v in open( "Impulse_time_axis.txt", "r" ).readlines() ] )
print type(tm), tm.shape

output = np.array( [ float(v) for v in open( "Output_data.txt", "r" ).readlines() ] )
print type(output), output.shape

tout = np.array( [ float(v) for v in open( "Output_time_axis.txt", "r" ).readlines() ] )
print type(tout), tout.shape

# Define the function that calculates the residuals
def residuals(  coeffs, output, tm ):
    dt, alpha1, alpha2 = coeffs
    res = np.zeros( tm.shape )
    for n,t in enumerate(tm):
        # integrate to "t"
        value = sum( Pm[:n]*(1-np.e**( -(alpha1 * (tm[:n]+dt))) )*np.e**(-(alpha2 * (tm[:n]+dt))) )
        # retrieve output at t+dt
        n1 = (np.abs(tout - (t+dt) )).argmin()
        # construct the residual
        res[n] =  output[n1] - value
    return res

# Initial guess for the parameters
x0 = (10.,1.,1.)

# Run the least squares routine
coeffs, flag = leastsq( residuals, x0, args=(output,tm) )

# Report the results
print( coeffs )
print( flag )
Related