-1

Assume that I have two functions describing one phenomena in the same range (x-axis). Both are sharing same parameters, but also can have their own. How can I fit them or minimize the errors to experimental data using SciPy or Lmfit >>AT ONCE<<? I think about something as below:

def f1(x_val, p1, p2, p3):
    some_code_1

def f2(x_val, p1, p2, p4):
    some_code_2

exp_data_1 = np.loadtxt("./mydata1.txt")
exp_data_x1 = exp_data_1[:,0]
exp_data_y1 = exp_data_1[:,1]

exp_data_2 = np.loadtxt("./mydata2.txt")
exp_data_x1 = exp_data_1[:,0]
exp_data_y1 = exp_data_1[:,1]

xxx = np.linspace(0, 1, 1000)
popt, pcov = curve_fit((f1,f2), (exp_data_y1, exp_data_y2), xxx)

And popt should contain only one set of parameters p1, p2, p3, p4, proper for both functions f1, f2. I will be very glad for any suggestions, hints. For more intuition is a problem with fitting the functions to hysteresis loop.

all the best

Mimi
  • 95
  • 1
  • 10

2 Answers2

0

I'm not entirely sure if the values you can get out of this will make any sense for your goal, but why not use a third function which calls the first two, and returns the average of the results?

# some semi-random data
xdata_1 = np.linspace(-200, 200, 100)
ydata_1 = 200*np.random.random(100) + np.linspace(-10, 100, 100)

xdata_2 = np.linspace(50, 250, 100)
ydata_2 = 200*np.random.random(100) - (xdata_2**2/100)#linspace(100, -1000, 100)


# fit functions
def fit1(x, p1, p2):
    return p1*x + p2

def fit2(x, p1, p2, p3):
    return p1*x**2 + p2*x + p3

# this function calls both fit functions and returns the average result
def fit_general(x, p1, p2, p3):
    y1 = fit1(x, p1, p2)
    y2 = fit2(x, p1, p2, p3)
    return (y1 + y2) / 2


# now fit with the combined dataset
xdata = np.concatenate((xdata_1, xdata_2))
ydata = np.concatenate((ydata_1, ydata_2))
popt, pcov = curve_fit(fit_general, xdata, ydata)


# plot the result
plotrange = np.linspace(-200, 250, 100)
plt.scatter(xdata_1, ydata_1)
plt.scatter(xdata_2, ydata_2)
plt.plot(plotrange, fit_general(plotrange, *popt), color='k')
plt.grid(alpha=0.4)

Resulting plot:

example plot

I doubt this works well for hysteresis models though.

It might also be useful to use a single function which takes both x and y as inputs (see Python curve_fit with multiple independent variables) if that's mathematically possible, or to rewrite your fit functions as a fit using polar coordinates or a single parametric curve (a bit like this model: https://en.wikipedia.org/wiki/Stoner%E2%80%93Wohlfarth_model).

asdf101
  • 569
  • 5
  • 18
0

If the x-axis is the same for both experimental results and you would like to have only one set of parameters for both functions f1, f2 at the output, then why not merging these two experimental datasets and use only one function which is multiplication of f1 and f2 (f1*f2). It should give proper optimization and one set of parameters.

Similar to what asdfCYBER has shown but instead f3 is an average of two, I would use f3=f1*f2.