Project

Curve Fitting

from scipy.optimize import curve_fit
import numpy as np
import matplotlib.pyplot as plt

\"\"\"
Challenge - Week5 : Curve Fitting
\"\"\"

# approximate data with linear curve
def linear_func(t,a,b):
    return a*t + b

# approximate data with quadtratic curve
def quad_func(t,a,b,c):
    return a*pow(t,2) + b*t + c

# approximate data with quadtratic curve
def cubic_func(t,a,b,c,d):
    return a*pow(t,3) + b*pow(t,2) + c*t +d

# trial curve
def trial_func(t,e,a,b,c,d):
    return e*pow(t,4) + a*pow(t,3) + b*pow(t,2) + c*t +d

# reading data from given file
def read_data():
    temperature = []
    Cp_val      = []
    for line in open(\'data_challenge\'):
        temperature.append(float(line.split(\',\')[0]))
        Cp_val.append(float(line.split(\',\')[1]))
    return temperature,Cp_val

# Curve fitting - solve
temp, cp = read_data()

# Finding optimum parameters using curve_fit
popt1, pcov1 = curve_fit(linear_func, temp, cp)
popt2, pcov2 = curve_fit(quad_func, temp, cp)
popt3, pcov2 = curve_fit(cubic_func, temp, cp)
popt4, pcov3 = curve_fit(trial_func, temp, cp)


# Finding cp values as per the new curve fitting
cp_new1 = linear_func(np.array(temp),*popt1)
cp_new2 = quad_func(np.array(temp),*popt2)
cp_new3 = cubic_func(np.array(temp),*popt3)
cp_new4 = trial_func(np.array(temp),*popt4)


# Plotting
plt.figure()
plt.plot(temp, cp, \'k\', linewidth = 2)
plt.plot(temp, cp_new1, \'b-.\')
plt.plot(temp, cp_new2, \'g-.\')
plt.plot(temp, cp_new3, \'c-.\')
plt.plot(temp, cp_new4, \'r-.\')
plt.legend([\'Actual\', \'Linear curve fit\', \'Quad Curve fit\', \'Cubic curve fit\', \'4th order curve fit\'])
plt.xlabel(\'Temperature[K]\')
plt.ylabel(\'Cp\')
plt.show()


\"\"\"
Applying cubic and linear curve fit to same data split into parts
\"\"\"

a = int(len(temp)/2)
temp_a = temp[:a]
temp_b = temp[a:]
cp_a   = cp[:a]
cp_b   = cp[a:]


# finding parameters
# Linear case
popt_alin, pcov_alin = curve_fit(linear_func, temp_a, cp_a)
popt_blin, pcov_blin = curve_fit(linear_func, temp_b, cp_b)

# Cubic case
popt_acube, pcov_acube = curve_fit(cubic_func, temp_a, cp_a)
popt_bcube, pcov_bcube = curve_fit(cubic_func, temp_b, cp_b)


# Finding cp
# Linear case
cp_alin = linear_func(np.array(temp_a),*popt_alin)
cp_blin = linear_func(np.array(temp_b),*popt_blin)

# Cubic case
cp_acube = cubic_func(np.array(temp_a),*popt_acube)
cp_bcube = cubic_func(np.array(temp_b),*popt_bcube)


# plotting
# linear case
plt.figure()
plt.plot(temp, cp, \'g\', linewidth = 2)
plt.plot(temp_a, cp_alin, \'b-.\')
plt.plot(temp_b, cp_blin, \'r-.\')
plt.plot(temp, cp_new1, \'c-.\')
plt.legend([\'Actual\', \'Linear curve- data part A\',\'Linear curve- data part B\', \'Linear curve over entire data\' ])
plt.xlabel(\'Temperature[K]\')
plt.ylabel(\'Cp\')
plt.show()

# cubic case
plt.figure()
plt.plot(temp, cp, \'g\', linewidth = 2)
plt.plot(temp_a, cp_acube, \'b-.\')
plt.plot(temp_b, cp_bcube, \'r-.\')
plt.plot(temp, cp_new3, \'c-.\')
plt.legend([\'Actual\', \'Cubic curve- data part A\',\'Cubic curve- data part B\',\'Cubic curve over entire data\' ])
plt.xlabel(\'Temperature[K]\')
plt.ylabel(\'Cp\')
plt.show()

1.] What does popt and pcov mean?

popt : gives the array of optimized parameters of the curve fit polynomial. It is the best fit value where sum of the squared residual of the function value and original data is minimum.

pcov : it is a 2d array of covariance(error) of popt values. Using this we can determine the standard deviations of the parameters and the correlation between the parameters.

2.] What does np.array(temperature) do?

It converts the list of tempertature to an array type on which operations can be performed. Else it would give a type error as follows

TypeError: can\'t multiply sequence by non-int of type \'numpy.float64\'

3.] What does the * in *popt mean?

The * unpacks the popt arrays to the number of arguments needed for the function. In the code popt can have 3/4/5 parameters. So code is generalised when calling the function.

4.] Write code to fit a linear and cubic polynomial for the Cp data. Explain if your results are good or bad.

Linear: We can see the amount of error between the actual curve and fitted curve is very high. This is not a good estimation

Cubic: We can see that we are getting way better results as the order of the polynomial increases. This can be a pretty good estimation.

Ofcourse as you increase the order of the polynomial you could get a better resut. But the computational effort would also increase. So this should be taken into account.

5.] What needs to be done in order to make the curve fit perfect?

A sufficiently high order polynomial can be used ( max order :number of data -1). But it is not preferred to use large degree( 7 or higher) polynomials. We can see in the code, 4th order polynomial is giving a better result than cubic polynomial.

One thing that can be done is to split the curve(data) into multiple parts and fit to the linear/cubic curve . This should give a better accuracy as you are fitting the same parameters for less number of data. This can be seen in the code. For linear case the second half of the data already gives a better fit. The cubic case, gives a very good fit on seeing the graph. This can be verified by checking the errors and comparing. If we divide the data into further smaller parts we can get a better accuracy with lower order of the polynomial itself

For a good curve fit there are options like Lagrange interpolation polynomial, splines, parametric curves, bezier curves

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.