Issue
I have my goodness of fit line. However, I want to shift the fit line down to touch the lowest leftmost point on the graph.
Here is my minimally reproduceable example below and what I have come up with thus far.
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import uncertainties.unumpy as unp
import uncertainties as unc
class FatigueCurve:
def __init__(self) -> None:
# make the data
y = [862.0,716.0,862.0,793.0,690.0,690.0,621.0,621.0,690.0,552.0,552.0,552.0]
x = [1.0,1.0,11.0,160.0,563.0,680.0,4130.0,7528.0,9768.0,77843.0,115530.0,394498.0]
...
Code for goodness of fit
...
x1y1 = min(px),max(nom)
x2y2 = max(px),min(nom)
crossProducts = []
for x,y in zip(cycles, stress):
x3y3 = (x,y)
crossProducts.append((x2y2[0] - x1y1[0]) * (x3y3[1] - x1y1[1]) - (x2y2[1] - x1y1[1]) * (x3y3[0] - x1y1[0]))
closestToZero = np.inf
for item in crossProducts:
if item < closestToZero:
closestToZero = item
# this is where I would like to shift the goodness of fit line down to closestToZero
# plot
fig, ax = plt.subplots()
ax.semilogx(x, y, 'bo', label='data')
ax.plot(px, nom, c='red', label='curve fit')
plt.show()
def powerLaw(self, S, A, B):
return A * np.power(S,B)
if __name__ == "__main__":
FatigueCurve()
What I would like to do now is shift the line down using the greatest cross product.
Solution
If you want your fitted curve go through the lowest point, you can use the sigma
parameter. sigma
can act as weight to "force" the fitted curve. What you need is to fix the std
to 1 for this particular point. In fact, you fix the degree of freedom to fit the curve.
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
import uncertainties.unumpy as unp
import uncertainties as unc
class FatigueCurve:
def __init__(self) -> None:
# make the data
y = [125,190,335,279,212,186,186,345,345,345,276,276,190,207,276,207]
x = [1996768,593319,674,17700,138596,1612585,920132,2080,1244,779,19034,38474,18865901,3000000,21100,8266515]
# HERE: force the weights
w = np.zeros_like(y) + np.std(y)
w[np.argmin(y)] = 1
# HERE: use sigma=w as parameter of curve_fit
popt, pcov = curve_fit(self.powerLaw, x, y, sigma=w, maxfev=1000)
a,b = unc.correlated_values(popt, pcov)
px = np.linspace(min(x), max(x), len(x))
py = a*np.power(px,b)
nom = unp.nominal_values(py)
print(px)
print(py)
# plot
fig, ax = plt.subplots()
ax.semilogx(x, y, 'bo', label='data')
ax.plot(px, nom, c='red', label='curve fit')
plt.show()
def powerLaw(self, S, A, B):
return A * np.power(S,B)
if __name__ == "__main__":
FatigueCurve()
Answered By - Corralien
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.