/* * hrs-scaling.c * * Intensity scaling using generalised HRS target function * * (c) 2006-2010 Thomas White * * Part of CrystFEL - crystallography with a FEL * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "image.h" #include "peaks.h" #include "symmetry.h" #include "geometry.h" #include "cell.h" /* Maximum number of iterations of NLSq scaling per macrocycle. */ #define MAX_CYCLES (30) static void show_matrix_eqn(gsl_matrix *M, gsl_vector *v, int r) { int i, j; for ( i=0; icpeaks; if ( k != a ) continue; for ( hi=0; hin_cpeaks; hi++ ) { double ic, sigi; signed int ha, ka, la; if ( !spots[hi].valid ) continue; if ( spots[hi].p < 0.1 ) continue; get_asymm(spots[hi].h, spots[hi].k, spots[hi].l, &ha, &ka, &la, sym); if ( ha != hat ) continue; if ( ka != kat ) continue; if ( la != lat ) continue; ic = spots[hi].intensity / spots[hi].p; sigi = sqrt(fabs(ic)); val += 1.0 / pow(sigi, 2.0); } } return val; } static double s_vha(signed int hat, signed int kat, signed int lat, struct image *images, int n, const char *sym, int a) { int k; double val = 0.0; for ( k=0; kcpeaks; if ( k != a ) continue; for ( hi=0; hin_cpeaks; hi++ ) { double ic, sigi; signed int ha, ka, la; if ( !spots[hi].valid ) continue; if ( spots[hi].p < 0.1 ) continue; get_asymm(spots[hi].h, spots[hi].k, spots[hi].l, &ha, &ka, &la, sym); if ( ha != hat ) continue; if ( ka != kat ) continue; if ( la != lat ) continue; ic = spots[hi].intensity / spots[hi].p; sigi = sqrt(fabs(ic)); val += ic / pow(sigi, 2.0); /* Yes, I know this = 1 */ } } return val; } static double s_uh(struct image *images, int n, signed int h, signed int k, signed int l, const char *sym) { int a; double val = 0.0; for ( a=0; a crossed ) acomp--; for ( h=0; hh; const signed int k = it->k; const signed int l = it->l; /* Determine the "solution" vector component */ vha = s_vha(h, k, l, images, n, sym, a); uha = s_uha(h, k, l, images, n, sym, a); uh = s_uh(images, n, h, k, l, sym); Ih = s_vh(images, n, h, k, l, sym) / uh; rha = vha - image_a->osf * uha * Ih; vc = Ih * rha; vc_tot += vc; /* Determine the matrix component */ for ( b=0; b a ) continue; if ( b == crossed ) continue; bcomp = b; if ( b > crossed ) bcomp--; vhb = s_vha(h, k, l, images, n, sym, b); uhb = s_uha(h, k, l, images, n, sym, b); rhb = vhb - image_b->osf * uhb * Ih; mc = (rha*vhb + vha*rhb - vha*vhb) / uh; if ( a == b ) { mc += pow(Ih, 2.0) * uha; } tval = gsl_matrix_get(M, acomp, bcomp); gsl_matrix_set(M, acomp, bcomp, tval+mc); gsl_matrix_set(M, bcomp, acomp, tval+mc); } } gsl_vector_set(v, acomp, vc_tot); } show_matrix_eqn(M, v, n-1); #if 0 /* Fox and Holmes method */ gsl_eigen_symmv_workspace *work; gsl_vector *e_val; gsl_matrix *e_vec; int val; work = gsl_eigen_symmv_alloc(n); e_val = gsl_vector_alloc(n); e_vec = gsl_matrix_alloc(n, n); val = gsl_eigen_symmv(M, e_val, e_vec, work); STATUS("gsl_eigen_symmv said %i (%s)\n", val, gsl_strerror(val)); gsl_eigen_symmv_free(work); show_eigen(e_vec, e_val, n); #endif shifts = gsl_vector_alloc(n-1); gsl_linalg_HH_solve(M, v, shifts); max_shift = 0.0; STATUS("Shifts:\n"); for ( a=0; a= crossed ) aimg++; STATUS("%3i: %5.2f\n", aimg, shift); images[aimg].osf += shift; if ( fabs(shift) > fabs(max_shift) ) { max_shift = fabs(shift); } } gsl_vector_free(shifts); gsl_matrix_free(M); gsl_vector_free(v); return max_shift; } static double *lsq_intensities(struct image *images, int n, ReflItemList *obs, const char *sym) { double *I_full; int i; I_full = new_list_intensity(); for ( i=0; ih, it->k, it->l, &h, &k, &l, sym); /* For each frame */ for ( m=0; m 0.01) && (i < MAX_CYCLES) ); for ( m=0; m