continuous two line segment with smooth fitted break point #780
-
Hello, this example shows a two line segment with smooth fitted break point. It is a reduced example, the target functions are more complex so the available multi line fitting packages are not a solution. Which is the correct syntax to realize this, please? When setting additional parameters (https://lmfit.github.io/lmfit-py/constraints.html), theses parameters are also send to the called functions, is it possible to suppress this? Thanyk you code with format import matplotlib.pyplot as plt
import lmfit
import numpy as np
from scipy.special import erf
plt.ion()
def plot_02(xx1, xx2, yy3):
fig, axs = plt.subplots(1, squeeze=False, figsize=(1.5 * 5, 1.5 * 4))
axs = axs.flat
axs[0].plot(np.append(xx1, xx2), result_fit.best_fit, label='fit')
axs[0].plot(np.append(xx1, xx2), yy3, label='data')
axs[0].legend(loc='upper center', bbox_to_anchor=(0.5, -0.35), \
fancybox=True, shadow=False, ncol=7, fontsize=6)
plt.tight_layout()
plt.show(block=False)
def linear(m, a, x):
answer = m * x + a
return answer
def fit_line(xx, yy):
params = lmfit.Parameters()
params.add('a', value=1, vary=True)
params.add('m', value=1, vary=True)
model = lmfit.Model(func=linear, independent_vars=['x'], param_names=['a', 'm'], nan_policy='omit')
result = model.fit(yy, params=params, x=xx)
return result
def two_lines_smooth(x, x0, m1, a1, m2, a2):
# https://lmfit.github.io/lmfit-py/faq.html#faq-discrete-params
m1 = linear(m=m1, a=a1, x=x)
m2 = linear(m=m2, a=a2, x=x)
# step up from 0 to 1 at x0: (erf(x-x0)+1)/2
# step down from 1 to 0 at x0: (1-erf(x-x0))/2
model = m2 * (erf(x - x0) + 1) / 2 + m1 * (1 - erf(x - x0)) / 2
return model
def two_with_border(m1, a1, m2, a2, x0, x):
result = np.piecewise(x,
[x < x0, x >= x0],
[lambda x: linear(m=m1, a=a1, x=x),
lambda x: linear(m=m2, a=a2, x=x)])
return result
def fit_multi_line_smooth(xx, yy):
params = lmfit.Parameters()
params.add('a1', value=1.1, vary=True)
params.add('m1', value=1.1, vary=True)
params.add('a2', value=-2.5, vary=True)
params.add('m2', value=19.0, vary=True)
params.add('x0', value=5.5, vary=True)
model_linear_lm = lmfit.Model(func=two_lines_smooth, independent_vars=['x'],
param_names=['a1', 'm1', 'a2', 'm2', 'x0'], nan_policy='omit')
result_linear_10 = model_linear_lm.fit(yy, params=params, x=xx, method='least_squares')
return result_linear_10
#%%
np.random.seed(1001)
n = 50
xx1 = np.linspace(0, 5, n, endpoint=False)
yy1 = linear(m=1, a=1, x=xx1) + np.random.randn(n)
xx2 = np.linspace(5, 10, n, endpoint=True)
yy2 = linear(m=-2, a=18, x=xx2) + np.random.randn(n)
result_fit = fit_multi_line_smooth(xx=np.append(xx1, xx2), yy=np.append(yy1, yy2))
lmfit.report_fit(result_fit)
yy3 = two_with_border(x=np.append(xx1, xx2), x0=result_fit.params['x0'].value,
m1=result_fit.params['m1'].value,
a1=result_fit.params['a1'].value,
m2=result_fit.params['m2'].value,
a2=result_fit.params['a2'].value)
plot_02(xx1=xx1, xx2=xx2, yy3=yy3) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
Please confirm that you read https://lmfit.github.io/lmfit-py/faq.html#can-parameters-be-used-for-array-indices-or-discrete-values
No. When using When using the more general-purpose I don't really understand your code or what point it is trying to make. It seems like you're trying something two different ways. I don't know why. If you want us to understand something about your code, tell us what that is. And, if you want us to understand your code, format it correctly. |
Beta Was this translation helpful? Give feedback.
-
This solution is doing exactly what was mathematically expected. Thank you very much. |
Beta Was this translation helpful? Give feedback.
This solution is doing exactly what was mathematically expected.
Thank you very much.