Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
273 views
in Technique[技术] by (71.8m points)

numpy - Unable to plot an accurate tangent to a curvature in Python

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: enter image description here

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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
at point [{xVal:.1f}, {yVal:.1f}]
with slope {slopeVal:.2f}
and intercept {intercVal:.2f}" )
ax.set_ylim(0.8 * y.min(), 1.2 * y.max())
ax.legend()

plt.show()

enter image description here


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...