static void calc_either_side(Crystal *cr, double incr_val, int *valid, long double *vals[3], int refine, PartialityModel pmodel) { RefList *compare; struct image *image = crystal_get_image(cr); if ( (refine != REF_DIV) ) { Crystal *cr_new; /* Crystal properties */ cr_new = new_shifted_crystal(cr, refine, -incr_val); compare = find_intersections(image, cr_new, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 0, pmodel); cell_free(crystal_get_cell(cr_new)); crystal_free(cr_new); reflist_free(compare); cr_new = new_shifted_crystal(cr, refine, +incr_val); compare = find_intersections(image, cr_new, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 2, pmodel); cell_free(crystal_get_cell(cr_new)); crystal_free(cr_new); reflist_free(compare); } else { struct image im_moved; /* "Image" properties */ im_moved = *image; shift_parameter(&im_moved, refine, -incr_val); compare = find_intersections(&im_moved, cr, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 0, pmodel); reflist_free(compare); im_moved = *image; shift_parameter(&im_moved, refine, +incr_val); compare = find_intersections(&im_moved, cr, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 2, pmodel); reflist_free(compare); } }
static void calc_either_side(Crystal *cr, double incr_val, int *valid, long double *vals[3], int refine, PartialityModel pmodel) { RefList *compare; struct image *image = crystal_get_image(cr); struct image im_moved; im_moved = *image; shift_parameter(&im_moved, refine, -incr_val); compare = find_intersections(&im_moved, cr, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 0); reflist_free(compare); im_moved = *image; shift_parameter(&im_moved, refine, +incr_val); compare = find_intersections(&im_moved, cr, pmodel); scan_partialities(crystal_get_reflections(cr), compare, valid, vals, 2); reflist_free(compare); }
static double guide_dev(Crystal *cr, const RefList *full) { double dev = 0.0; /* For each reflection */ Reflection *refl; RefListIterator *iter; for ( refl = first_refl(crystal_get_reflections(cr), &iter); refl != NULL; refl = next_refl(refl, iter) ) { double G, p; signed int h, k, l; Reflection *full_version; double I_full, I_partial; if ( (get_intensity(refl) < 3.0*get_esd_intensity(refl)) || (get_partiality(refl) < MIN_PART_REFINE) ) continue; get_indices(refl, &h, &k, &l); assert((h!=0) || (k!=0) || (l!=0)); full_version = find_refl(full, h, k, l); if ( full_version == NULL ) continue; /* Some reflections may have recently become scalable, but * scale_intensities() might not yet have been called, so the * full version may not have been calculated yet. */ G = crystal_get_osf(cr); p = get_partiality(refl); I_partial = get_intensity(refl); I_full = get_intensity(full_version); //STATUS("%3i %3i %3i %5.2f %5.2f %5.2f %5.2f %5.2f\n", // h, k, l, G, p, I_partial, I_full, // I_partial - p*G*I_full); dev += pow(I_partial - p*G*I_full, 2.0); } return dev; }
static void write_crystal(Stream *st, Crystal *cr, int include_reflections) { UnitCell *cell; RefList *reflist; double asx, asy, asz; double bsx, bsy, bsz; double csx, csy, csz; double a, b, c, al, be, ga; double rad; fprintf(st->fh, CRYSTAL_START_MARKER"\n"); cell = crystal_get_cell(cr); assert(cell != NULL); cell_get_parameters(cell, &a, &b, &c, &al, &be, &ga); fprintf(st->fh, "Cell parameters %7.5f %7.5f %7.5f nm," " %7.5f %7.5f %7.5f deg\n", a*1.0e9, b*1.0e9, c*1.0e9, rad2deg(al), rad2deg(be), rad2deg(ga)); cell_get_reciprocal(cell, &asx, &asy, &asz, &bsx, &bsy, &bsz, &csx, &csy, &csz); fprintf(st->fh, "astar = %+9.7f %+9.7f %+9.7f nm^-1\n", asx/1e9, asy/1e9, asz/1e9); fprintf(st->fh, "bstar = %+9.7f %+9.7f %+9.7f nm^-1\n", bsx/1e9, bsy/1e9, bsz/1e9); fprintf(st->fh, "cstar = %+9.7f %+9.7f %+9.7f nm^-1\n", csx/1e9, csy/1e9, csz/1e9); fprintf(st->fh, "lattice_type = %s\n", str_lattice(cell_get_lattice_type(cell))); fprintf(st->fh, "centering = %c\n", cell_get_centering(cell)); fprintf(st->fh, "unique_axis = %c\n", cell_get_unique_axis(cell)); rad = crystal_get_profile_radius(cr); fprintf(st->fh, "profile_radius = %.5f nm^-1\n", rad/1e9); reflist = crystal_get_reflections(cr); if ( reflist != NULL ) { fprintf(st->fh, "diffraction_resolution_limit" " = %.2f nm^-1 or %.2f A\n", crystal_get_resolution_limit(cr)/1e9, 1e10 / crystal_get_resolution_limit(cr)); fprintf(st->fh, "num_reflections = %i\n", num_reflections(reflist)); fprintf(st->fh, "num_saturated_reflections = %lli\n", crystal_get_num_saturated_reflections(cr)); } if ( include_reflections ) { if ( reflist != NULL ) { fprintf(st->fh, REFLECTION_START_MARKER"\n"); if ( AT_LEAST_VERSION(st, 2, 2) ) { write_stream_reflections(st->fh, reflist); } else { /* This function writes like a normal reflection * list was written in stream 2.1 */ write_stream_reflections_2_1(st->fh, reflist); } fprintf(st->fh, REFLECTION_END_MARKER"\n"); } else { fprintf(st->fh, "No integrated reflections.\n"); } } fprintf(st->fh, CRYSTAL_END_MARKER"\n"); }
/* 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; }