Unable to plot an accurate tangent to a curvature in Python

谁都会走 提交于 2021-02-10 14:21:16

问题


I have a dataset for curvature and I need to find the tangent to the curve but unfortunately, this is a bit far from the curve. Kindly guide me the issue solution related to the problem. Thank you! My code is as follows:

fig, ax1 = plt.subplots()
chData_m = efficient.get('Car.Road.y')  

x_fit = chData_m.timestamps
y_fit = chData_m.samples

fittedParameters = np.polyfit(x_fit[:],y_fit[:],1)

f = plt.figure(figsize=(800/100.0, 600/100.0), dpi=100)
axes = f.add_subplot(111)

    # first the raw data as a scatter plot
axes.plot(x_fit, y_fit,  'D')

    # create data for the fitted equation plot
xModel = np.linspace(min(x_fit), max(x_fit))
yModel = np.polyval(fittedParameters, xModel)

    # now the model as a line plot
axes.plot(xModel, yModel)

axes.set_xlabel('X Data') # X axis data label
axes.set_ylabel('Y Data') # Y axis data label

    # polynomial derivative from numpy
deriv = np.polyder(fittedParameters)

    # for plotting
minX = min(x_fit)
maxX = max(x_fit)

    # value of derivative (slope) at a specific X value, so
    # that a straight line tangent can be plotted at the point
    # you might place this code in a loop to animate
pointVal = 10.0 # example X value
y_value_at_point = np.polyval(fittedParameters, pointVal)
slope_at_point = np.polyval(deriv, pointVal)

ylow = (minX - pointVal) * slope_at_point + y_value_at_point
yhigh = (maxX - pointVal) * slope_at_point + y_value_at_point

    # now the tangent as a line plot
axes.plot([minX, maxX], [ylow, yhigh])

plt.show()
plt.close('all') # clean up after using pyplot

and the output is:


回答1:


I am not sure how you wanted to use numpy polyfit/polyval to determine the tangent formula. I describe here a different approach. The advantage of this approach is that it does not have any assumptions about the nature of the function. The disadvantage is that it will not work for vertical tangents.
To be on the safe side, I have considered both cases, i.e., that the evaluated x-value is a data point in your series and that it is not. Some problems may arise because I see that you mention timestamps in your question without specifying their nature by providing a toy dataset - so, this version may or may not work with the datetime objects or timestamps of your original data:

import matplotlib.pyplot as plt
import numpy as np

#generate fake data with unique random x-values between 0 and 70
def func(x, a=0, b=100, c=1, n=3.5):
    return a + (b/(1+(c/x)**n))
np.random.seed(123)
x = np.random.choice(range(700000), 100)/10000
x.sort()
y = func(x, 1, 2, 15, 2.4)


#data point to evaluate
xVal = 29

#plot original data
fig, ax = plt.subplots()
ax.plot(x, y, c="blue", label="data")

#calculate gradient
slope = np.gradient(y, x)

#determine slope and intercept at xVal
ind1 = (np.abs(x - xVal)).argmin()
#case 1 the value is a data point
if xVal == x[ind1]:
    yVal, slopeVal = y[ind1], slope[ind1]    
#case 2 the value lies between to data points
#in which case we approximate linearly from the two nearest data points
else:
    if xVal < x[ind1]:
        ind1, ind2 = ind1-1, ind1
    else:
        ind1, ind2 = ind1, ind1+1         
    yVal = y[ind1] + (y[ind2]-y[ind1]) * (xVal-x[ind1]) / (x[ind2]-x[ind1])
    slopeVal = slope[ind1] + (slope[ind2]-slope[ind1]) * (xVal-x[ind1]) / (x[ind2]-x[ind1])
intercVal = yVal - slopeVal * xVal    

ax.plot([x.min(), x.max()], [slopeVal*x.min()+intercVal, slopeVal*x.max()+intercVal], color="green", 
        label=f"tangent\nat point [{xVal:.1f}, {yVal:.1f}]\nwith slope {slopeVal:.2f}\nand intercept {intercVal:.2f}" )
ax.set_ylim(0.8 * y.min(), 1.2 * y.max())
ax.legend()

plt.show()



来源:https://stackoverflow.com/questions/65844149/unable-to-plot-an-accurate-tangent-to-a-curvature-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!