Curve fixing for function type: y = 10 ^ ((ax) / 10 * b)
Below is the distance (column y
) based on values ββfrom the sensor (column x
).
test.txt - content
x y
----------
-51.61 ,1.5
-51.61 ,1.5
-51.7 ,1.53
-51.91 ,1.55
-52.28 ,1.62
-52.35 ,1.63
-52.49 ,1.66
-52.78 ,1.71
-52.84 ,1.73
-52.90 ,1.74
-53.21 ,1.8
-53.43 ,1.85
-53.55 ,1.87
-53.71 ,1.91
-53.99 ,1.97
-54.13 ,2
-54.26 ,2.03
-54.37 ,2.06
-54.46 ,2.08
-54.59 ,2.11
-54.89 ,2.19
-54.94 ,2.2
-55.05 ,2.23
-55.11 ,2.24
-55.17 ,2.26
I would like to tweak a fit to find the constants a
and b
for the data in test.txt
based on this function:
Function y = 10^((a-x)/10*b)
I am using the following code:
import math
from numpy import genfromtxt
from scipy.optimize import curve_fit
inData = genfromtxt('test.txt',delimiter=',')
rssi_data = inData[:,0]
dist_data= inData[:,1]
print rssi_data
print dist_data
def func(x, a,b):
exp_val = (x-a)/(10.0*b)
return math.pow(10,exp_val)
coeffs, matcov = curve_fit(func,rssi_data,dist_data)
print(coeffs)
print(matcov)
The code does not execute successfully. Also I'm not sure if I am passing in the correct parameters curve_fit()
.
source to share
The function should handle arrays of numpy arrays, but currently it cannot because it math.pow
expects a scalar value. If I execute your code, I get this exception:
TypeError: only length-1 arrays can be converted to Python scanners
If you change your function to:
def func(x, a, b):
return 10 ** ((a - x) / (10 * b)) # ** is the power operator
It should work without exceptions:
>>> print(coeffs)
[-48.07485338 2.00667587]
>>> print(matcov)
[[ 3.59154631e-04 1.21357926e-04]
[ 1.21357926e-04 4.25732516e-05]]
Here's the complete code:
def func(x, a, b):
return 10 ** ((a - x) / (10 * b))
coeffs, matcov = curve_fit(func, rssi_data, dist_data)
# And some plotting for visualization
import matplotlib.pyplot as plt
%matplotlib notebook # only works in IPython notebooks
plt.figure()
plt.scatter(rssi_data, dist_data, label='measured')
x = np.linspace(rssi_data.min(), rssi_data.max(), 1000)
plt.plot(x, func(x, coeffs[0], coeffs[1]), label='fitted')
plt.legend()
source to share
I have confirmed the previous answer as it is correct for a programming problem. But looking closer, you don't need to establish a law of power:
y = 10^((a-x)/10*b) <=> log10(y) = log10(10^((a-x)/10*b))
<=> log10(y) = (a-x)/10*b
Use new variables:
z = log10(y), c = a/10*b and d = -1/10*b
And now you need to pick up the following:
z = dx + c
This is a straight line. One just needs to apply the above transformations to 2 items (x, y) => (x, log10 (y)) in the table and put a straight line to get c, d and therefore a, b.
I am writing this because perhaps you need to do this many times, and it is much easier (and more accurate) to do than fitting a force function. This also has implications when planning your experiment. You basically only need 2 points to get the general behavior if you know this is the correct fitting function.
Hope this helps. Hooray!
source to share