static double test_gradients(Crystal *cr, double incr_val, int refine, const char *str, const char *file, PartialityModel pmodel, int quiet, int plot) { Reflection *refl; RefListIterator *iter; long double *vals[3]; int i; int *valid; int nref; int n_good, n_invalid, n_small, n_nan, n_bad; RefList *reflections; FILE *fh = NULL; int ntot = 0; double total = 0.0; char tmp[32]; double *vec1; double *vec2; int n_line; double cc; reflections = find_intersections(crystal_get_image(cr), cr, pmodel); crystal_set_reflections(cr, reflections); nref = num_reflections(reflections); if ( nref < 10 ) { ERROR("Too few reflections found. Failing test by default.\n"); return 0.0; } vals[0] = malloc(nref*sizeof(long double)); vals[1] = malloc(nref*sizeof(long double)); vals[2] = malloc(nref*sizeof(long double)); if ( (vals[0] == NULL) || (vals[1] == NULL) || (vals[2] == NULL) ) { ERROR("Couldn't allocate memory.\n"); return 0.0; } valid = malloc(nref*sizeof(int)); if ( valid == NULL ) { ERROR("Couldn't allocate memory.\n"); return 0.0; } for ( i=0; i<nref; i++ ) valid[i] = 1; scan_partialities(reflections, reflections, valid, vals, 1, pmodel); calc_either_side(cr, incr_val, valid, vals, refine, pmodel); if ( plot ) { snprintf(tmp, 32, "gradient-test-%s.dat", file); fh = fopen(tmp, "w"); } vec1 = malloc(nref*sizeof(double)); vec2 = malloc(nref*sizeof(double)); if ( (vec1 == NULL) || (vec2 == NULL) ) { ERROR("Couldn't allocate memory.\n"); return 0.0; } n_invalid = 0; n_good = 0; n_nan = 0; n_small = 0; n_bad = 0; n_line = 0; i = 0; for ( refl = first_refl(reflections, &iter); refl != NULL; refl = next_refl(refl, iter) ) { long double grad1, grad2, grad; double cgrad; signed int h, k, l; get_indices(refl, &h, &k, &l); if ( !valid[i] ) { n_invalid++; i++; } else { double r1, r2, p; grad1 = (vals[1][i] - vals[0][i]) / incr_val; grad2 = (vals[2][i] - vals[1][i]) / incr_val; grad = (grad1 + grad2) / 2.0; i++; cgrad = p_gradient(cr, refine, refl, pmodel); get_partial(refl, &r1, &r2, &p); if ( isnan(cgrad) ) { n_nan++; continue; } if ( plot ) { fprintf(fh, "%e %Le\n", cgrad, grad); } vec1[n_line] = cgrad; vec2[n_line] = grad; n_line++; if ( (fabs(cgrad) < 5e-8) && (fabs(grad) < 5e-8) ) { n_small++; continue; } total += fabs(cgrad - grad); ntot++; if ( !within_tolerance(grad, cgrad, 5.0) || !within_tolerance(cgrad, grad, 5.0) ) { if ( !quiet ) { STATUS("!- %s %3i %3i %3i" " %10.2Le %10.2e ratio = %5.2Lf" " %10.2e %10.2e\n", str, h, k, l, grad, cgrad, cgrad/grad, r1, r2); } n_bad++; } else { //STATUS("OK %s %3i %3i %3i" // " %10.2Le %10.2e ratio = %5.2Lf" // " %10.2e %10.2e\n", // str, h, k, l, grad, cgrad, cgrad/grad, // r1, r2); n_good++; } } } STATUS("%3s: %3i within 5%%, %3i outside, %3i nan, %3i invalid, " "%3i small. ", str, n_good, n_bad, n_nan, n_invalid, n_small); if ( plot ) { fclose(fh); } cc = gsl_stats_correlation(vec1, 1, vec2, 1, n_line); STATUS("CC = %+f\n", cc); return cc; }
/* Perform one cycle of post refinement on 'image' against 'full' */ static double pr_iterate(Crystal *cr, const RefList *full, PartialityModel pmodel, int *n_filtered) { gsl_matrix *M; gsl_vector *v; gsl_vector *shifts; int param; Reflection *refl; RefListIterator *iter; RefList *reflections; double max_shift; int nref = 0; const int verbose = 0; int num_params = 0; enum gparam rv[32]; *n_filtered = 0; /* If partiality model is anything other than "unity", refine all the * geometrical parameters */ if ( pmodel != PMODEL_UNITY ) { rv[num_params++] = GPARAM_ASX; rv[num_params++] = GPARAM_ASY; rv[num_params++] = GPARAM_ASZ; rv[num_params++] = GPARAM_BSX; rv[num_params++] = GPARAM_BSY; rv[num_params++] = GPARAM_BSZ; rv[num_params++] = GPARAM_CSX; rv[num_params++] = GPARAM_CSY; rv[num_params++] = GPARAM_CSZ; } STATUS("Refining %i parameters.\n", num_params); reflections = crystal_get_reflections(cr); M = gsl_matrix_calloc(num_params, num_params); v = gsl_vector_calloc(num_params); /* Construct the equations, one per reflection in this image */ for ( refl = first_refl(reflections, &iter); refl != NULL; refl = next_refl(refl, iter) ) { signed int ha, ka, la; double I_full, delta_I; double w; double I_partial; int k; double p, l; Reflection *match; double gradients[num_params]; /* Find the full version */ get_indices(refl, &ha, &ka, &la); match = find_refl(full, ha, ka, la); if ( match == NULL ) continue; if ( (get_intensity(refl) < 3.0*get_esd_intensity(refl)) || (get_partiality(refl) < MIN_PART_REFINE) || (get_redundancy(match) < 2) ) continue; I_full = get_intensity(match); /* Actual measurement of this reflection from this pattern? */ I_partial = get_intensity(refl) / crystal_get_osf(cr); p = get_partiality(refl); l = get_lorentz(refl); /* Calculate the weight for this reflection */ w = pow(get_esd_intensity(refl), 2.0); w += l * p * I_full * pow(get_esd_intensity(match), 2.0); w = pow(w, -1.0); /* Calculate all gradients for this reflection */ for ( k=0; k<num_params; k++ ) { gradients[k] = p_gradient(cr, rv[k], refl, pmodel) * l; } for ( k=0; k<num_params; k++ ) { int g; double v_c, v_curr; for ( g=0; g<num_params; g++ ) { double M_c, M_curr; /* Matrix is symmetric */ if ( g > k ) continue; M_c = gradients[g] * gradients[k]; M_c *= w * pow(I_full, 2.0); M_curr = gsl_matrix_get(M, k, g); gsl_matrix_set(M, k, g, M_curr + M_c); gsl_matrix_set(M, g, k, M_curr + M_c); } delta_I = I_partial - (l * p * I_full); v_c = w * delta_I * I_full * gradients[k]; v_curr = gsl_vector_get(v, k); gsl_vector_set(v, k, v_curr + v_c); } nref++; } if ( verbose ) { STATUS("The original equation:\n"); show_matrix_eqn(M, v); } //STATUS("%i reflections went into the equations.\n", nref); if ( nref == 0 ) { crystal_set_user_flag(cr, 2); gsl_matrix_free(M); gsl_vector_free(v); return 0.0; } max_shift = 0.0; shifts = solve_svd(v, M, n_filtered, verbose); if ( shifts != NULL ) { for ( param=0; param<num_params; param++ ) { double shift = gsl_vector_get(shifts, param); apply_shift(cr, rv[param], shift); //STATUS("Shift %i: %e\n", param, shift); if ( fabs(shift) > max_shift ) max_shift = fabs(shift); } } else { crystal_set_user_flag(cr, 3); } gsl_matrix_free(M); gsl_vector_free(v); gsl_vector_free(shifts); return max_shift; }