def do_polynomial_fit(x, params): n_terms = len(params) y = flex.double(x.size()) for i in range(len(params)): y += params[i] * flex.pow(x, i) fit = curve_fitting.univariate_polynomial_fit(x, y, degree=n_terms - 1) assert approx_equal(params, fit.params, eps=1e-4)
def do_polynomial_fit(x, params): n_terms = len(params) y = flex.double(x.size()) for i in range(len(params)): y += params[i] * flex.pow(x, i) fit = curve_fitting.univariate_polynomial_fit(x, y, degree=n_terms-1) assert approx_equal(params, fit.params, eps=1e-4)
def log_fit(x, y, degree=5): """Fit the values log(y(x)) then return exp() to this fit. x, y should be iterables containing floats of the same size. The order is the order of polynomial to use for this fit. This will be useful for e.g. I/sigma.""" fit = curve_fitting.univariate_polynomial_fit( x, flex.log(y), degree=degree, max_iterations=100 ) f = curve_fitting.univariate_polynomial(*fit.params) return flex.exp(f(x))
def log_inv_fit(x, y, degree=5): """Fit the values log(1 / y(x)) then return the inverse of this fit. x, y should be iterables, the order of the polynomial for the transformed fit needs to be specified. This will be useful for e.g. Rmerge.""" fit = curve_fitting.univariate_polynomial_fit( x, flex.log(1 / y), degree=degree, max_iterations=100 ) f = curve_fitting.univariate_polynomial(*fit.params) return 1 / flex.exp(f(x))
def polynomial_fit(x, y, degree=5): """ Fit a polynomial to the values y(x) and return this fit x, y should be iterables containing floats of the same size. The order is the order of polynomial to use for this fit. This will be useful for e.g. I/sigma. """ fit = curve_fitting.univariate_polynomial_fit( x, y, degree=degree, max_iterations=100 ) f = curve_fitting.univariate_polynomial(*fit.params) return f(x)
def exercise_gaussian_fit(): # test fitting of a gaussian def do_gaussian_fit(scale, mu, sigma): start = mu - 6 * sigma stop = mu + 6 * sigma step = (stop - start) / 1000 x = flex.double(frange(start, stop, step)) y = scale * flex.exp(-flex.pow2(x - mu) / (2 * sigma**2)) fit = curve_fitting.single_gaussian_fit(x, y) assert approx_equal(fit.a, scale, 1e-4) assert approx_equal(fit.b, mu, eps=1e-4) assert approx_equal(fit.c, sigma, eps=1e-4) for i in range(10): scale = random.random() * 1000 sigma = (random.random() + 0.0001) * 10 mu = (-1)**random.randint(0, 1) * random.random() * 1000 functor = curve_fitting.gaussian(scale, mu, sigma) start = mu - 6 * sigma stop = mu + 6 * sigma step = (stop - start) / 1000 x = flex.double(frange(start, stop, step)) fd_grads = finite_differences(functor, x) assert approx_equal(functor.partial_derivatives(x), fd_grads, 1e-4) do_gaussian_fit(scale, mu, sigma) # if we take the log of a gaussian we can fit a parabola scale = 123 mu = 3.2 sigma = 0.1 x = flex.double(frange(2, 4, 0.01)) y = scale * flex.exp(-flex.pow2(x - mu) / (2 * sigma**2)) # need to be careful to only use values of y > 0 eps = 1e-15 x = flex.double([x[i] for i in range(x.size()) if y[i] > eps]) y = flex.double([y[i] for i in range(y.size()) if y[i] > eps]) fit = curve_fitting.univariate_polynomial_fit(x, flex.log(y), degree=2) c, b, a = fit.params assert approx_equal(mu, -b / (2 * a)) assert approx_equal(sigma * sigma, -1 / (2 * a)) # test multiple gaussian fits gaussians = [ curve_fitting.gaussian(0.3989538, 3.7499764, 0.7500268), curve_fitting.gaussian(0.7978957, 6.0000004, 0.5000078) ] x = flex.double(frange(0, 10, 0.1)) y = flex.double(x.size()) for i in range(len(gaussians)): g = gaussians[i] scale, mu, sigma = g.a, g.b, g.c y += g(x) starting_gaussians = [ curve_fitting.gaussian(1, 4, 1), curve_fitting.gaussian(1, 5, 1) ] fit = curve_fitting.gaussian_fit(x, y, starting_gaussians) for g1, g2 in zip(gaussians, fit.gaussians): assert approx_equal(g1.a, g2.a, eps=1e-4) assert approx_equal(g1.b, g2.b, eps=1e-4) assert approx_equal(g1.c, g2.c, eps=1e-4) # use example of 5-gaussian fit from here: # http://research.stowers-institute.org/efg/R/Statistics/MixturesOfDistributions/index.htm gaussians = [ curve_fitting.gaussian(0.10516252, 23.32727, 2.436638), curve_fitting.gaussian(0.46462715, 33.09053, 2.997594), curve_fitting.gaussian(0.29827916, 41.27244, 4.274585), curve_fitting.gaussian(0.08986616, 51.24468, 5.077521), curve_fitting.gaussian(0.04206501, 61.31818, 7.070303) ] x = flex.double(frange(0, 80, 0.1)) y = flex.double(x.size()) for i in range(len(gaussians)): g = gaussians[i] scale, mu, sigma = g.a, g.b, g.c y += g(x) termination_params = scitbx.lbfgs.termination_parameters( min_iterations=500) starting_gaussians = [ curve_fitting.gaussian(1, 21, 2.1), curve_fitting.gaussian(1, 30, 2.8), curve_fitting.gaussian(1, 40, 2.2), curve_fitting.gaussian(1, 51, 1.2), curve_fitting.gaussian(1, 60, 2.3) ] fit = curve_fitting.gaussian_fit(x, y, starting_gaussians, termination_params=termination_params) y_calc = fit.compute_y_calc() assert approx_equal(y, y_calc, eps=1e-2) have_cma_es = libtbx.env.has_module("cma_es") if have_cma_es: fit = curve_fitting.cma_es_minimiser(starting_gaussians, x, y) y_calc = fit.compute_y_calc() assert approx_equal(y, y_calc, eps=5e-2)
def exercise_gaussian_fit(): # test fitting of a gaussian def do_gaussian_fit(scale, mu, sigma): start = mu - 6 * sigma stop = mu + 6 * sigma step = (stop - start)/1000 x = flex.double(frange(start, stop, step)) y = scale * flex.exp(-flex.pow2(x - mu) / (2 * sigma**2)) fit = curve_fitting.single_gaussian_fit(x, y) assert approx_equal(fit.a, scale, 1e-4) assert approx_equal(fit.b, mu, eps=1e-4) assert approx_equal(fit.c, sigma, eps=1e-4) for i in range(10): scale = random.random() * 1000 sigma = (random.random() + 0.0001) * 10 mu = (-1)**random.randint(0,1) * random.random() * 1000 functor = curve_fitting.gaussian(scale, mu, sigma) start = mu - 6 * sigma stop = mu + 6 * sigma step = (stop - start)/1000 x = flex.double(frange(start, stop, step)) fd_grads = finite_differences(functor, x) assert approx_equal(functor.partial_derivatives(x), fd_grads, 1e-4) do_gaussian_fit(scale, mu, sigma) # if we take the log of a gaussian we can fit a parabola scale = 123 mu = 3.2 sigma = 0.1 x = flex.double(frange(2, 4, 0.01)) y = scale * flex.exp(-flex.pow2(x - mu) / (2 * sigma**2)) # need to be careful to only use values of y > 0 eps = 1e-15 x = flex.double([x[i] for i in range(x.size()) if y[i] > eps]) y = flex.double([y[i] for i in range(y.size()) if y[i] > eps]) fit = curve_fitting.univariate_polynomial_fit(x, flex.log(y), degree=2) c, b, a = fit.params assert approx_equal(mu, -b/(2*a)) assert approx_equal(sigma*sigma, -1/(2*a)) # test multiple gaussian fits gaussians = [curve_fitting.gaussian(0.3989538, 3.7499764, 0.7500268), curve_fitting.gaussian(0.7978957, 6.0000004, 0.5000078)] x = flex.double(frange(0, 10, 0.1)) y = flex.double(x.size()) for i in range(len(gaussians)): g = gaussians[i] scale, mu, sigma = g.a, g.b, g.c y += g(x) starting_gaussians = [ curve_fitting.gaussian(1, 4, 1), curve_fitting.gaussian(1, 5, 1)] fit = curve_fitting.gaussian_fit(x, y, starting_gaussians) for g1, g2 in zip(gaussians, fit.gaussians): assert approx_equal(g1.a, g2.a, eps=1e-4) assert approx_equal(g1.b, g2.b, eps=1e-4) assert approx_equal(g1.c, g2.c, eps=1e-4) # use example of 5-gaussian fit from here: # http://research.stowers-institute.org/efg/R/Statistics/MixturesOfDistributions/index.htm gaussians = [curve_fitting.gaussian(0.10516252, 23.32727, 2.436638), curve_fitting.gaussian(0.46462715, 33.09053, 2.997594), curve_fitting.gaussian(0.29827916, 41.27244, 4.274585), curve_fitting.gaussian(0.08986616, 51.24468, 5.077521), curve_fitting.gaussian(0.04206501, 61.31818, 7.070303)] x = flex.double(frange(0, 80, 0.1)) y = flex.double(x.size()) for i in range(len(gaussians)): g = gaussians[i] scale, mu, sigma = g.a, g.b, g.c y += g(x) termination_params = scitbx.lbfgs.termination_parameters( min_iterations=500) starting_gaussians = [curve_fitting.gaussian(1, 21, 2.1), curve_fitting.gaussian(1, 30, 2.8), curve_fitting.gaussian(1, 40, 2.2), curve_fitting.gaussian(1, 51, 1.2), curve_fitting.gaussian(1, 60, 2.3)] fit = curve_fitting.gaussian_fit( x, y, starting_gaussians, termination_params=termination_params) y_calc = fit.compute_y_calc() assert approx_equal(y, y_calc, eps=1e-2) have_cma_es = libtbx.env.has_module("cma_es") if have_cma_es: fit = curve_fitting.cma_es_minimiser(starting_gaussians, x, y) y_calc = fit.compute_y_calc() assert approx_equal(y, y_calc, eps=5e-2)