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()

.

+3


source to share


2 answers


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()

      

enter image description here

+5


source


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!

+1


source







All Articles