Large negative exponents make the exponential function close to zero, thus making the least squares algorithm insensitive to your fitting parameters.
Therefore, while fitting exponential functions with exponents depending on time stamps, the best is to adjust the time exponent by excluding the time of the first data point, changing it from:
f = exp(-x*t)
to:
t0 = t[0] # place this outside loops
f = exp(-x*(t - t0))
Applying this concept to your code leads to:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
time, temp = np.loadtxt('test.txt', unpack=True)
t0 = time[0]
# Newton cooling law fitting
def TEMP_FIT(t, T0, k, Troom):
print(T0, k, Troom)
return T0 * np.exp(-k*(t - t0)) + Troom
popt, pcov = curve_fit(TEMP_FIT, time, temp)
# Plotting
plt.figure()
plt.plot(time, temp, 'bo--',label='Heater off', alpha=0.5)
plt.plot(time, TEMP_FIT(time, *popt), label='Newton Cooling Law Fit')
plt.xlim(-25, 250)
plt.xlabel('Time (min)')
plt.ylabel('Temperature ($^\circ$C)')
ax = plt.gca()
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
plt.legend(fontsize=8)
plt.savefig('test.png', bbox_inches='tight')
The result is:
Removing the first point of your sample: