From b3854b29262d2f67eae90c1e54b39b09e49ea66b Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 7 Jul 2010 16:51:26 +0200 Subject: compare_hkl: Use minimisation to determine the right scale factor --- src/statistics.c | 171 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 142 insertions(+), 29 deletions(-) (limited to 'src/statistics.c') diff --git a/src/statistics.c b/src/statistics.c index d78dde9e..da3d95c4 100644 --- a/src/statistics.c +++ b/src/statistics.c @@ -16,11 +16,27 @@ #include #include +#include +#include #include "statistics.h" #include "utils.h" +struct r_params { + const double *ref1; + const unsigned int *c1; + const double *ref2; + const unsigned int *c2; + int fom; +}; + +enum { + R_2, + R_MERGE, +}; + + double stat_scale_intensity(const double *ref1, const unsigned int *c1, const double *ref2, const unsigned int *c2) { @@ -45,38 +61,39 @@ double stat_scale_intensity(const double *ref1, const unsigned int *c1, } -double stat_r2(const double *ref1, const unsigned int *c1, - const double *ref2, const unsigned int *c2, double *scalep) +double stat_scale_sqrti(const double *ref1, const unsigned int *c1, + const double *ref2, const unsigned int *c2) { double top = 0.0; double bot = 0.0; - double scale; int i; - scale = stat_scale_intensity(ref1, c1, ref2, c2); - *scalep = scale; /* Start from i=1 -> skip central beam */ for ( i=1; i skip central beam */ for ( i=1; ifom) { + case R_MERGE : + return internal_rmerge(rp->ref1, rp->c1, + rp->ref2, rp->c2, scale); + case R_2 : + return internal_r2(rp->ref1, rp->c1, + rp->ref2, rp->c2, scale); + } + + ERROR("No such FoM!\n"); + abort(); +} + + +static double r_minimised(const double *ref1, const unsigned int *c1, + const double *ref2, const unsigned int *c2, + double *scalep, int fom) +{ + gsl_function F; + gsl_min_fminimizer *s; + int status; + double scale = 1.0; + struct r_params rp; + int iter = 0; + + rp.ref1 = ref1; + rp.ref2 = ref2; + rp.c1 = c1; + rp.c2 = c2; + rp.fom = fom; + + F.function = &calc_r; + F.params = &rp; + + s = gsl_min_fminimizer_alloc(gsl_min_fminimizer_brent); + + /* Initial guess */ + switch ( fom ) { + case R_MERGE : + scale = stat_scale_sqrti(ref1, c1, ref2, c2); + break; + case R_2 : + scale = stat_scale_intensity(ref1, c1, ref2, c2); + break; + } + //STATUS("Initial scale factor estimate: %5.2e\n", scale); + + /* Probably within an order of magnitude either side */ + gsl_min_fminimizer_set(s, &F, scale, scale/10.0, scale*10.0); + + do { + + double lo, up; + + /* Iterate */ + gsl_min_fminimizer_iterate(s); + + /* Get the current estimate */ + scale = gsl_min_fminimizer_x_minimum(s); + lo = gsl_min_fminimizer_x_lower(s); + up = gsl_min_fminimizer_x_upper(s); + + /* Check for convergence */ + status = gsl_min_test_interval(lo, up, 0.001, 0.0); + + iter++; + + } while ( status == GSL_CONTINUE ); + + if (status != GSL_SUCCESS) { + ERROR("Scale factor minimisation failed.\n"); + } + + gsl_min_fminimizer_free(s); + + //STATUS("Final scale factor: %5.2e\n", scale); + *scalep = scale; + return calc_r(scale, &rp); +} + + +double stat_rmerge(const double *ref1, const unsigned int *c1, + const double *ref2, const unsigned int *c2, + double *scalep) +{ + return r_minimised(ref1, c1, ref2, c2, scalep, R_MERGE); +} + + +double stat_r2(const double *ref1, const unsigned int *c1, + const double *ref2, const unsigned int *c2, + double *scalep) +{ + return r_minimised(ref1, c1, ref2, c2, scalep, R_2); +} -- cgit v1.2.3