def test_logistic_and_linear_function(self): x_data = np.arange(-10, 10, 0.1) _ = logistic(x_data, x0=0, alpha=1) self.assertTrue(logistic(0, x0=0, alpha=1) == 0.5) _ = linear_function(x_data, 1, 2) self.assertTrue(linear_function(0, 1, 2) == 2) self.assertTrue(linear_function(3, 1, 2) == 5)
def test_initial_estimate_fermi_linear(self, fig=None): expected_parameters = [0.01000295, 0.51806569, -4.88800525, 0.12838861, 0.25382811] x_data = np.arange(-20, 10, 0.1) y_data = FermiLinear(x_data, *expected_parameters) y_data += 0.005 * np.random.rand(y_data.size) linear_part, fermi_part = initFermiLinear(x_data, y_data, fig=fig) ylin = linear_function(x_data, *linear_part) yr = y_data - ylin cc, A = _estimate_fermi_model_center_amplitude(x_data, yr, fig=fig) np.testing.assert_almost_equal(cc, expected_parameters[2], decimal=1) np.testing.assert_almost_equal(A, expected_parameters[3], decimal=1) self.assertTrue(fermi_part is not None) plt.close('all')
def initFermiLinear(x_data, y_data, fig=None): """ Initialization of fitting a FermiLinear function. First the linear part is estimated, then the Fermi part of the function. Args: x_data (array): data for independent variable y_data (array): dependent variable fig (int) : figure number Returns: linear_part (array) fermi_part (array) """ xdata = np.array(x_data) ydata = np.array(y_data) n = xdata.size nx = int(np.ceil(n / 5)) if nx < 4: p1, _ = scipy.optimize.curve_fit(linear_function, np.array(xdata[0:100]), np.array(ydata[0:100])) a = p1[0] b = p1[1] linear_part = [a, b] ylin = linear_function(xdata, linear_part[0], linear_part[1]) cc = np.mean(xdata) A = 0 T = np.std(xdata) / 10 fermi_part = [cc, A, T] else: # guess initial linear part mx = np.mean(xdata) my = np.mean(ydata) dx = np.hstack((np.diff(xdata[0:nx]), np.diff(xdata[-nx:]))) dx = np.mean(dx) dd = np.hstack((np.diff(ydata[0:nx]), np.diff(ydata[-nx:]))) dd = np.convolve(dd, np.array([1., 1, 1]) / 3) # smooth if dd.size > 15: dd = np.array(sorted(dd)) w = int(dd.size / 10) a = np.mean(dd[w:-w]) / dx else: a = np.mean(dd) / dx b = my - a * mx linear_part = [a, b] ylin = linear_function(xdata, *linear_part) # subtract linear part yr = ydata - ylin cc, A = _estimate_fermi_model_center_amplitude(xdata, yr) T = np.std(xdata) / 100 linear_part[1] = linear_part[1] - A / 2 # correction fermi_part = [cc, A, T] yr = ydata - linear_function(xdata, *linear_part) if fig is not None: yf = FermiLinear(xdata, *linear_part, *fermi_part) xx = np.hstack((xdata[0:nx], xdata[-nx:])) yy = np.hstack((ydata[0:nx], ydata[-nx:])) plt.figure(fig) plt.clf() plt.plot(xdata, ydata, '.b', label='raw data') plt.plot(xx, yy, 'ok') qtt.pgeometry.plot2Dline([-1, 0, cc], ':c', label='center') plt.plot(xdata, ylin, '-c', alpha=.5, label='fitted linear function') plt.plot(xdata, yf, '-m', label='fitted FermiLinear function') plt.title('initFermiLinear', fontsize=12) plt.legend(numpoints=1) plt.figure(fig + 1) plt.clf() # TODO: When nx < 4 and fig is not None -> yr is undefined plt.plot(xdata, yr, '.b', label='Fermi part') fermi_part_values = Fermi(xdata, cc, A, T) plt.plot(xdata, fermi_part_values, '-m', label='initial estimate') plt.legend() return linear_part, fermi_part
def initFermiLinear(x_data, y_data, fig=None): """ Initalization of fitting a FermiLinear function. First the linear part is estimated, then the Fermi part of the function. """ xdata = np.array(x_data) ydata = np.array(y_data) n = xdata.size nx = int(np.ceil(n / 5)) if nx < 4: p1, _ = scipy.optimize.curve_fit(linear_function, np.array(xdata[0:100]), np.array(ydata[0:100])) a = p1[0] b = p1[1] ab = [a, b] y = linear_function(xdata, ab[0], ab[1]) cc = np.mean(xdata) A = 0 T = np.std(xdata) / 10 ff = [cc, A, T] else: # guess initial linear part mx = np.mean(xdata) my = np.mean(ydata) dx = np.hstack((np.diff(xdata[0:nx]), np.diff(xdata[-nx:]))) dx = np.mean(dx) dd = np.hstack((np.diff(ydata[0:nx]), np.diff(ydata[-nx:]))) dd = np.convolve(dd, np.array([1., 1, 1]) / 3) # smooth if dd.size > 15: dd = np.array(sorted(dd)) w = int(dd.size / 10) a = np.mean(dd[w:-w]) / dx else: a = np.mean(dd) / dx b = my - a * mx xx = np.hstack((xdata[0:nx], xdata[-nx:])) ab = [a, b] y = linear_function(xdata, ab[0], ab[1]) # subtract linear part yr = ydata - y cc = np.mean(xdata) h = int(xdata.size / 2) A = -(np.mean(yr[h:]) - np.mean(yr[:h])) T = np.std(xdata) / 10 ab[1] = ab[1] - A / 2 # correction ylin = linear_function(xdata, ab[0], ab[1]) # subtract linear part yr = ydata - ylin ff = [cc, A, T] if fig is not None: yf = FermiLinear(xdata, ab[0], ab[1], *ff) xx = np.hstack((xdata[0:nx], xdata[-nx:])) yy = np.hstack((ydata[0:nx], ydata[-nx:])) plt.figure(fig) plt.clf() plt.plot(xdata, ydata, '.b', label='raw data') plt.plot(xx, yy, 'ok') qtt.pgeometry.plot2Dline([-1, 0, cc], ':c', label='center') plt.plot(xdata, ylin, '-m', label='fitted linear function') plt.plot(xdata, yf, '-m', label='fitted FermiLinear function') plt.title('initFermiLinear', fontsize=12) plt.legend(numpoints=1) plt.figure(fig + 1) plt.clf() plt.plot(xdata, yr, '.b', label='Fermi part') f = Fermi(xdata, cc, A, T) plt.plot(xdata, f, '-m', label='estimated') plt.plot(xdata, f, '-m', label='estimated') # plt.plot(xdata, yr, '.b', label='Fermi part') plt.legend() return ab, ff