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 Crystal *new_shifted_crystal(Crystal *cr, int refine, double incr_val) { Crystal *cr_new; double r; UnitCell *cell; cr_new = crystal_copy(cr); if ( cr_new == NULL ) { ERROR("Failed to allocate crystal.\n"); return NULL; } crystal_set_image(cr_new, crystal_get_image(cr)); r = crystal_get_profile_radius(cr_new); switch ( refine ) { case REF_ASX : case REF_ASY : case REF_ASZ : case REF_BSX : case REF_BSY : case REF_BSZ : case REF_CSX : case REF_CSY : case REF_CSZ : cell = new_shifted_cell(crystal_get_cell(cr), refine, incr_val); crystal_set_cell(cr_new, cell); break; case REF_R : cell = cell_new_from_cell(crystal_get_cell(cr)); crystal_set_cell(cr_new, cell); crystal_set_profile_radius(cr_new, r + incr_val); break; default : ERROR("Can't shift %i\n", refine); break; } return cr_new; }
/* Return the gradient of partiality wrt parameter 'k' given the current status * of 'image'. */ double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel) { double glow, ghigh; double rlow, rhigh, p; struct image *image = crystal_get_image(cr); double R = crystal_get_profile_radius(cr); get_partial(refl, &rlow, &rhigh, &p); if ( k == GPARAM_R ) { double Rglow, Rghigh; double D, psph; D = rlow - rhigh; psph = volume_fraction(rlow, rhigh, R, pmodel); Rglow = volume_fraction_rgradient(rlow, R, pmodel); Rghigh = volume_fraction_rgradient(rhigh, R, pmodel); return 4.0*psph/(3.0*D) + (4.0*R/(3.0*D))*(Rglow - Rghigh); } /* Calculate the gradient of partiality wrt excitation error. */ glow = partiality_gradient(rlow, R, pmodel, rlow, rhigh); ghigh = partiality_gradient(rhigh, R, pmodel, rlow, rhigh); if ( k == GPARAM_DIV ) { double D, psph, ds; signed int hs, ks, ls; D = rlow - rhigh; psph = volume_fraction(rlow, rhigh, R, pmodel); get_symmetric_indices(refl, &hs, &ks, &ls); ds = 2.0 * resolution(crystal_get_cell(cr), hs, ks, ls); return (ds/2.0)*(glow+ghigh) - 4.0*R*psph*ds/(3.0*D*D); } return r_gradient(crystal_get_cell(cr), k, refl, image) * (glow-ghigh); }
struct prdata pr_refine(Crystal *cr, const RefList *full, PartialityModel pmodel) { double dev; int i; const int verbose = 0; struct prdata prdata; double mean_p_change = 0.0; prdata.refined = 0; prdata.n_filtered = 0; /* Don't refine crystal if scaling was bad */ if ( crystal_get_user_flag(cr) != 0 ) return prdata; if ( verbose ) { dev = guide_dev(cr, full); STATUS("\n"); /* Deal with progress bar */ STATUS("Before iteration: dev = %10.5e\n", dev); } i = 0; do { double asx, asy, asz; double bsx, bsy, bsz; double csx, csy, csz; double dev; cell_get_reciprocal(crystal_get_cell(cr), &asx, &asy, &asz, &bsx, &bsy, &bsz, &csx, &csy, &csz); pr_iterate(cr, full, pmodel, &prdata.n_filtered); update_partialities(cr, pmodel); if ( verbose ) { dev = guide_dev(cr, full); STATUS("PR Iteration %2i: dev = %10.5e\n", i+1, dev); } i++; } while ( (mean_p_change > 0.01) && (i < MAX_CYCLES) ); if ( crystal_get_user_flag(cr) == 0 ) { prdata.refined = 1; } return prdata; }
/* Apply the given shift to the 'k'th parameter of 'image'. */ static void apply_shift(Crystal *cr, int k, double shift) { double t; struct image *image = crystal_get_image(cr); switch ( k ) { case GPARAM_DIV : if ( isnan(shift) ) { ERROR("NaN divergence shift\n"); } else { image->div += shift; if ( image->div < 0.0 ) image->div = 0.0; } break; case GPARAM_R : t = crystal_get_profile_radius(cr); t += shift; crystal_set_profile_radius(cr, t); break; case GPARAM_ASX : case GPARAM_ASY : case GPARAM_ASZ : case GPARAM_BSX : case GPARAM_BSY : case GPARAM_BSZ : case GPARAM_CSX : case GPARAM_CSY : case GPARAM_CSZ : apply_cell_shift(crystal_get_cell(cr), k, shift); break; default : ERROR("No shift defined for parameter %i\n", k); abort(); } }
static void read_crystal(Stream *st, struct image *image, StreamReadFlags srf) { char line[1024]; char *rval = NULL; struct rvec as, bs, cs; int have_as = 0; int have_bs = 0; int have_cs = 0; int have_latt = 0; int have_cen = 0; int have_ua = 0; char centering = 'P'; char unique_axis = '*'; LatticeType lattice_type = L_TRICLINIC; Crystal *cr; int n; Crystal **crystals_new; cr = crystal_new(); if ( cr == NULL ) { ERROR("Failed to allocate crystal!\n"); return; } do { float u, v, w, lim, rad; char c; rval = fgets(line, 1023, st->fh); /* Trouble? */ if ( rval == NULL ) break; chomp(line); if ( (srf & STREAM_READ_UNITCELL) && (sscanf(line, "astar = %f %f %f", &u, &v, &w) == 3) ) { as.u = u*1e9; as.v = v*1e9; as.w = w*1e9; have_as = 1; } if ( (srf & STREAM_READ_UNITCELL) && (sscanf(line, "bstar = %f %f %f", &u, &v, &w) == 3) ) { bs.u = u*1e9; bs.v = v*1e9; bs.w = w*1e9; have_bs = 1; } if ( (srf & STREAM_READ_UNITCELL) && (sscanf(line, "cstar = %f %f %f", &u, &v, &w) == 3) ) { cs.u = u*1e9; cs.v = v*1e9; cs.w = w*1e9; have_cs = 1; } if ( (srf & STREAM_READ_UNITCELL) && (sscanf(line, "centering = %c", &c) == 1) ) { if ( !have_cen ) { centering = c; have_cen = 1; } else { ERROR("Duplicate centering ignored.\n"); } } if ( (srf & STREAM_READ_UNITCELL) && (sscanf(line, "unique_axis = %c", &c) == 1) ) { if ( !have_ua ) { unique_axis = c; have_ua = 1; } else { ERROR("Duplicate unique axis ignored.\n"); } } if ( (srf & STREAM_READ_UNITCELL) && (strncmp(line, "lattice_type = ", 15) == 0) ) { if ( !have_latt ) { lattice_type = lattice_from_str(line+15); have_latt = 1; } else { ERROR("Duplicate lattice type ignored.\n"); } } if ( strncmp(line, "num_saturated_reflections = ", 28) == 0 ) { int n = atoi(line+28); crystal_set_num_saturated_reflections(cr, n); } if ( sscanf(line, "diffraction_resolution_limit = %f nm^-1", &lim) == 1 ) { crystal_set_resolution_limit(cr, lim*1e9); } if ( sscanf(line, "profile_radius = %f nm^-1", &rad) == 1 ) { crystal_set_profile_radius(cr, rad*1e9); } if ( (strcmp(line, REFLECTION_START_MARKER) == 0) && (srf & STREAM_READ_REFLECTIONS) ) { RefList *reflist; /* The reflection list format in the stream diverges * after 2.2 */ if ( AT_LEAST_VERSION(st, 2, 2) ) { reflist = read_stream_reflections(st->fh); } else { reflist = read_stream_reflections_2_1(st->fh); } if ( reflist == NULL ) { ERROR("Failed while reading reflections\n"); break; } crystal_set_reflections(cr, reflist); } if ( strcmp(line, CRYSTAL_END_MARKER) == 0 ) break; } while ( 1 ); if ( have_as && have_bs && have_cs ) { UnitCell *cell; cell = crystal_get_cell(cr); if ( cell != NULL ) { ERROR("Duplicate cell found in stream!\n"); ERROR("I'll use the most recent one.\n"); cell_free(cell); } cell = cell_new_from_reciprocal_axes(as, bs, cs); if ( have_cen && have_ua && have_latt ) { cell_set_centering(cell, centering); cell_set_unique_axis(cell, unique_axis); cell_set_lattice_type(cell, lattice_type); } /* else keep default triclinic P */ crystal_set_cell(cr, cell); have_as = 0; have_bs = 0; have_cs = 0; have_latt = 0; have_ua = 0; have_cen = 0; } /* Unused at the moment */ crystal_set_mosaicity(cr, 0.0); /* Add crystal to the list for this image */ n = image->n_crystals+1; crystals_new = realloc(image->crystals, n*sizeof(Crystal *)); if ( crystals_new == NULL ) { ERROR("Failed to expand crystal list!\n"); } else { image->crystals = crystals_new; image->crystals[image->n_crystals++] = cr; } }
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"); }