diff options
Diffstat (limited to 'libcrystfel/src')
-rw-r--r-- | libcrystfel/src/geometry.c | 163 | ||||
-rw-r--r-- | libcrystfel/src/peaks.c | 34 |
2 files changed, 80 insertions, 117 deletions
diff --git a/libcrystfel/src/geometry.c b/libcrystfel/src/geometry.c index 218c0fee..24669aef 100644 --- a/libcrystfel/src/geometry.c +++ b/libcrystfel/src/geometry.c @@ -99,112 +99,70 @@ static signed int locate_peak(double x, double y, double z, double k, } -static double excitation_error(double xl, double yl, double zl, - double ds, double k, double divergence, - double tt) +static double partiality(double rlow, double rhigh, double r) { - double al; - double r; - double delta; - - al = M_PI_2 - asin(-zl/ds); - - r = ( ds * sin(al) / sin(tt) ) - k; - - delta = sqrt(2.0 * pow(ds, 2.0) * (1.0-cos(divergence))); - if ( divergence > 0.0 ) { - r += delta; - } else { - r -= delta; - } - - return r; -} - - -static double partiality(double r1, double r2, double r) -{ - double q1, q2; - double p1, p2; + double qlow, qhigh; + double plow, phigh; /* Calculate degrees of penetration */ - q1 = (r1 + r)/(2.0*r); - q2 = (r2 + r)/(2.0*r); + qlow = (rlow + r)/(2.0*r); + qhigh = (rhigh + r)/(2.0*r); /* Convert to partiality */ - p1 = 3.0*pow(q1,2.0) - 2.0*pow(q1,3.0); - p2 = 3.0*pow(q2,2.0) - 2.0*pow(q2,3.0); + plow = 3.0*pow(qlow,2.0) - 2.0*pow(qlow,3.0); + phigh = 3.0*pow(qhigh,2.0) - 2.0*pow(qhigh,3.0); - return p2 - p1; + return plow - phigh; } static Reflection *check_reflection(struct image *image, signed int h, signed int k, signed int l, - double asx, double asy, double asz, - double bsx, double bsy, double bsz, - double csx, double csy, double csz) + double xl, double yl, double zl) { const int output = 0; - double xl, yl, zl; - double ds, ds_sq; + double tl; double rlow, rhigh; /* "Excitation error" */ signed int p; /* Panel number */ double xda, yda; /* Position on detector */ - int close, inside; double part; /* Partiality */ - int clamp_low = 0; - int clamp_high = 0; - double bandwidth = image->bw; - double divergence = image->div; - double lambda = image->lambda; - double klow, kcen, khigh; /* Wavenumber */ + int clamp_low, clamp_high; + double klow, khigh; /* Wavenumber */ Reflection *refl; - double tt, psi; - - /* "low" gives the largest Ewald sphere, - * "high" gives the smallest Ewald sphere. */ - klow = 1.0/(lambda - lambda*bandwidth/2.0); - kcen = 1.0/lambda; - khigh = 1.0/(lambda + lambda*bandwidth/2.0); - - /* Get the coordinates of the reciprocal lattice point */ - xl = h*asx + k*bsx + l*csx; - yl = h*asy + k*bsy + l*csy; - zl = h*asz + k*bsz + l*csz; - - ds_sq = modulus_squared(xl, yl, zl); /* d*^2 */ - ds = sqrt(ds_sq); + double cet, cez; - /* Simple (fast) check to reject reflection if it's "in front" */ - psi = atan2(zl, sqrt(xl*xl + yl*yl)); - if ( psi - atan2(image->profile_radius, ds) > divergence ) return NULL; + /* "low" gives the largest Ewald sphere (wavelength short => k large) + * "high" gives the smallest Ewald sphere (wavelength long => k small) + */ + klow = 1.0/(image->lambda - image->lambda*image->bw/2.0); + khigh = 1.0/(image->lambda + image->lambda*image->bw/2.0); - tt = angle_between(0.0, 0.0, 1.0, xl, yl, zl+kcen); - if ( tt > deg2rad(90.0) ) return NULL; + /* If the point is looking "backscattery", reject it straight away */ + if ( zl < -khigh/2.0 ) return NULL; - /* Calculate excitation errors */ - rlow = excitation_error(xl, yl, zl, ds, klow, -divergence/2.0, tt); - rhigh = excitation_error(xl, yl, zl, ds, khigh, +divergence/2.0, tt); + tl = sqrt(xl*xl + yl*yl); - /* Is the reciprocal lattice point close to either extreme of - * the sphere, maybe just outside the "Ewald volume"? */ - close = (fabs(rlow) < image->profile_radius) - || (fabs(rhigh) < image->profile_radius); + cet = -sin(image->div/2.0) * khigh; + cez = -cos(image->div/2.0) * khigh; + rhigh = khigh - distance(cet, cez, tl, zl); /* Loss of precision */ - /* Is the reciprocal lattice point somewhere between the - * extremes of the sphere, i.e. inside the "Ewald volume"? */ - inside = signbit(rlow) ^ signbit(rhigh); + cet = sin(image->div/2.0) * klow; + cez = -cos(image->div/2.0) * klow; + rlow = klow - distance(cet, cez, tl, zl); /* Loss of precision */ - /* Can't be both inside and close */ - if ( inside ) close = 0; - - /* Neither? Skip it. */ - if ( !(close || inside) ) return NULL; + if ( (signbit(rlow) == signbit(rhigh)) + && (fabs(rlow) > image->profile_radius) + && (fabs(rhigh) > image->profile_radius) ) return NULL; /* If the "lower" Ewald sphere is a long way away, use the * position at which the Ewald sphere would just touch the - * reflection. */ + * reflection. + * + * The six possible combinations of clamp_{low,high} (including + * zero) correspond to the six situations in Table 3 of Rossmann + * et al. (1979). + */ + clamp_low = 0; clamp_high = 0; if ( rlow < -image->profile_radius ) { rlow = -image->profile_radius; clamp_low = -1; @@ -213,7 +171,6 @@ static Reflection *check_reflection(struct image *image, rlow = +image->profile_radius; clamp_low = +1; } - /* Likewise the "higher" Ewald sphere */ if ( rhigh < -image->profile_radius ) { rhigh = -image->profile_radius; clamp_high = -1; @@ -222,16 +179,13 @@ static Reflection *check_reflection(struct image *image, rhigh = +image->profile_radius; clamp_high = +1; } - assert(clamp_low <= clamp_high); - /* The six possible combinations of clamp_{low,high} (including - * zero) correspond to the six situations in Table 3 of Rossmann - * et al. (1979). */ + assert(clamp_low >= clamp_high); /* Calculate partiality */ part = partiality(rlow, rhigh, image->profile_radius); /* Locate peak on detector. */ - p = locate_peak(xl, yl, zl, kcen, image->det, &xda, &yda); + p = locate_peak(xl, yl, zl, 1.0/image->lambda, image->det, &xda, &yda); if ( p == -1 ) return NULL; /* Add peak to list */ @@ -252,6 +206,9 @@ static Reflection *check_reflection(struct image *image, RefList *find_intersections(struct image *image, UnitCell *cell) { + double ax, ay, az; + double bx, by, bz; + double cx, cy, cz; double asx, asy, asz; double bsx, bsy, bsz; double csx, csy, csz; @@ -270,17 +227,13 @@ RefList *find_intersections(struct image *image, UnitCell *cell) return NULL; } - cell_get_reciprocal(cell, &asx, &asy, &asz, - &bsx, &bsy, &bsz, - &csx, &csy, &csz); + cell_get_cartesian(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); - /* We add a horrific 20% fudge factor because bandwidth, divergence - * and so on mean reflections appear beyond the largest q */ - mres = 1.2 * largest_q(image); + mres = largest_q(image); - hmax = mres / modulus(asx, asy, asz); - kmax = mres / modulus(bsx, bsy, bsz); - lmax = mres / modulus(csx, csy, csz); + hmax = mres * modulus(ax, ay, az); + kmax = mres * modulus(bx, by, bz); + lmax = mres * modulus(cx, cy, cz); if ( (hmax >= 256) || (kmax >= 256) || (lmax >= 256) ) { ERROR("Unit cell is stupidly large.\n"); @@ -290,14 +243,23 @@ RefList *find_intersections(struct image *image, UnitCell *cell) if ( lmax >= 256 ) lmax = 255; } + cell_get_reciprocal(cell, &asx, &asy, &asz, + &bsx, &bsy, &bsz, + &csx, &csy, &csz); + for ( h=-hmax; h<=hmax; h++ ) { for ( k=-kmax; k<=kmax; k++ ) { for ( l=-lmax; l<=lmax; l++ ) { Reflection *refl; + double xl, yl, zl; + + /* Get the coordinates of the reciprocal lattice point */ + xl = h*asx + k*bsx + l*csx; + yl = h*asy + k*bsy + l*csy; + zl = h*asz + k*bsz + l*csz; - refl = check_reflection(image, h, k, l, - asx,asy,asz,bsx,bsy,bsz,csx,csy,csz); + refl = check_reflection(image, h, k, l, xl, yl, zl); if ( refl != NULL ) { add_refl_to_list(refl, reflections); @@ -333,13 +295,18 @@ void update_partialities(struct image *image) { Reflection *vals; double r1, r2, p, x, y; + double xl, yl, zl; signed int h, k, l; int clamp1, clamp2; get_symmetric_indices(refl, &h, &k, &l); - vals = check_reflection(image, h, k, l, - asx,asy,asz,bsx,bsy,bsz,csx,csy,csz); + /* Get the coordinates of the reciprocal lattice point */ + xl = h*asx + k*bsx + l*csx; + yl = h*asy + k*bsy + l*csy; + zl = h*asz + k*bsz + l*csz; + + vals = check_reflection(image, h, k, l, xl, yl, zl); if ( vals == NULL ) { set_redundancy(refl, 0); diff --git a/libcrystfel/src/peaks.c b/libcrystfel/src/peaks.c index 0d4ce64b..dac1a96e 100644 --- a/libcrystfel/src/peaks.c +++ b/libcrystfel/src/peaks.c @@ -52,14 +52,6 @@ #include "beam-parameters.h" -/* How close a peak must be to an indexed position to be considered "close" - * for the purposes of double hit detection and sanity checking. */ -#define PEAK_CLOSE (30.0) - -/* How close a peak must be to an indexed position to be considered "close" - * for the purposes of integration. */ -#define PEAK_REALLY_CLOSE (10.0) - /* Degree of polarisation of X-ray beam */ #define POL (1.0) @@ -184,8 +176,8 @@ int integrate_peak(struct image *image, int cfs, int css, out_lim_sq = pow(ir_out, 2.0); /* Estimate the background */ - for ( fs=-ir_out; fs<+ir_out; fs++ ) { - for ( ss=-ir_out; ss<+ir_out; ss++ ) { + for ( fs=-ir_out; fs<=+ir_out; fs++ ) { + for ( ss=-ir_out; ss<=+ir_out; ss++ ) { double val; uint16_t flags; @@ -233,8 +225,8 @@ int integrate_peak(struct image *image, int cfs, int css, pk_total = 0.0; pk_counts = 0; fsct = 0.0; ssct = 0.0; - for ( fs=-ir_inn; fs<+ir_inn; fs++ ) { - for ( ss=-ir_inn; ss<+ir_inn; ss++ ) { + for ( fs=-ir_inn; fs<=+ir_inn; fs++ ) { + for ( ss=-ir_inn; ss<=+ir_inn; ss++ ) { double val; uint16_t flags; @@ -541,9 +533,6 @@ int peak_sanity_check(struct image *image) struct integr_ind { - signed int h; - signed int k; - signed int l; double res; Reflection *refl; }; @@ -585,9 +574,6 @@ static struct integr_ind *sort_reflections(RefList *list, UnitCell *cell, get_indices(refl, &h, &k, &l); res = resolution(cell, h, k, l); - il[i].h = h; - il[i].k = k; - il[i].l = l; il[i].res = res; il[i].refl = refl; @@ -627,10 +613,12 @@ void integrate_reflections(struct image *image, int use_closer, int bgsub, double pfs, pss; int r; Reflection *refl; + signed int h, k, l; refl = il[i].refl; get_detector_pos(refl, &pfs, &pss); + get_indices(refl, &h, &k, &l); /* Is there a really close feature which was detected? */ if ( use_closer ) { @@ -643,11 +631,19 @@ void integrate_reflections(struct image *image, int use_closer, int bgsub, } else { f = NULL; } - if ( (f != NULL) && (d < PEAK_REALLY_CLOSE) ) { + + /* FIXME: Horrible hardcoded value */ + if ( (f != NULL) && (d < 10.0) ) { + + double exe; + + exe = get_excitation_error(refl); pfs = f->fs; pss = f->ss; + set_detector_pos(refl, exe, pfs, pss); + } } |