aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2010-10-27 20:02:59 +0200
committerThomas White <taw@physics.org>2012-02-22 15:27:04 +0100
commit533c10431f319c5cc943e49e4cefe58e8ce6c2cf (patch)
treefeae83731545f90d9a0b0105ba0a333e9815726c
parentf47803a3d004131493b20f9a3a3b5d9cccdaaf2a (diff)
facetron: Work on geometry
-rw-r--r--src/Makefile.am3
-rw-r--r--src/Makefile.in3
-rw-r--r--src/facetron.c45
-rw-r--r--src/geometry.c188
-rw-r--r--src/geometry.h3
-rw-r--r--src/image.h16
6 files changed, 178 insertions, 80 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 29949f7c..e2062d15 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -59,7 +59,8 @@ calibrate_detector_SOURCES = calibrate_detector.c utils.c hdf5-file.c image.c \
calibrate_detector_LDADD = @LIBS@
facetron_SOURCES = facetron.c cell.c hdf5-file.c utils.c detector.c peaks.c \
- image.c geometry.c reflections.c stream.c thread-pool.c
+ image.c geometry.c reflections.c stream.c thread-pool.c \
+ beam-parameters.c
facetron_LDADD = @LIBS@
cubeit_SOURCES = cubeit.c cell.c hdf5-file.c utils.c detector.c render.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index aa0519e8..54dff463 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -312,7 +312,8 @@ calibrate_detector_SOURCES = calibrate_detector.c utils.c hdf5-file.c image.c \
calibrate_detector_LDADD = @LIBS@
facetron_SOURCES = facetron.c cell.c hdf5-file.c utils.c detector.c peaks.c \
- image.c geometry.c reflections.c stream.c thread-pool.c
+ image.c geometry.c reflections.c stream.c thread-pool.c \
+ beam-parameters.c
facetron_LDADD = @LIBS@
cubeit_SOURCES = cubeit.c cell.c hdf5-file.c utils.c detector.c render.c \
diff --git a/src/facetron.c b/src/facetron.c
index 8d66d549..806ce54f 100644
--- a/src/facetron.c
+++ b/src/facetron.c
@@ -31,6 +31,7 @@
#include "geometry.h"
#include "peaks.h"
#include "thread-pool.h"
+#include "beam-parameters.h"
static void show_help(const char *s)
@@ -45,6 +46,9 @@ static void show_help(const char *s)
" (must be a file, not e.g. stdin)\n"
" -o, --output=<filename> Output filename. Default: facetron.hkl.\n"
" -g. --geometry=<file> Get detector geometry from file.\n"
+" -b, --beam=<file> Get beam parameters from file (provides initial\n"
+" values for parameters, and nominal wavelengths\n"
+" if no per-shot value is found in an HDF5 file.\n"
" -x, --prefix=<p> Prefix filenames from input file with <p>.\n"
" --basename Remove the directory parts of the filenames.\n"
" --no-check-prefix Don't attempt to correct the --prefix.\n"
@@ -91,6 +95,7 @@ static void integrate_image(int mytask, void *tasks)
int j, n;
struct hdfile *hdfile;
struct image *image = pargs->image;
+ double nominal_photon_energy = pargs->image->beam->photon_energy;
hdfile = hdfile_open(image->filename);
if ( hdfile == NULL ) {
@@ -102,34 +107,31 @@ static void integrate_image(int mytask, void *tasks)
return;
}
- if ( hdf5_read(hdfile, pargs->image, 0) ) {
+ /* FIXME: Nominal photon energy */
+ if ( hdf5_read(hdfile, pargs->image, 0, nominal_photon_energy) ) {
ERROR("Couldn't read '%s'\n", image->filename);
hdfile_close(hdfile);
return;
}
/* Figure out which spots should appear in this pattern */
- spots = find_intersections(image, image->indexed_cell,
- image->div, image->bw, &n, 0);
+ spots = find_intersections(image, image->indexed_cell, &n, 1);
/* For each reflection, estimate the partiality */
for ( j=0; j<n; j++ ) {
signed int h, k, l;
float i_partial;
- double p;
float xc, yc;
+ float i_full_est;
h = spots[j].h;
k = spots[j].k;
l = spots[j].l;
- /* Calculated partiality of this spot in this pattern */
- p = partiality(image, h, k, l);
-
/* Don't attempt to use spots with very small
* partialities, since it won't be accurate. */
- if ( p < 0.1 ) continue;
+ if ( spots[j].p < 0.1 ) continue;
/* Actual measurement of this reflection from this
* pattern? */
@@ -139,8 +141,10 @@ static void integrate_image(int mytask, void *tasks)
continue;
}
+ i_full_est = i_partial * spots[j].p;
+
pthread_mutex_lock(pargs->list_lock);
- integrate_intensity(pargs->i_full, h, k, l, i_partial);
+ integrate_intensity(pargs->i_full, h, k, l, i_full_est);
integrate_count(pargs->cts, h, k, l, 1);
if ( !find_item(pargs->obs, h, k, l) ) {
add_item(pargs->obs, h, k, l);
@@ -249,6 +253,7 @@ int main(int argc, char *argv[])
int n_total_patterns;
struct image *images;
int n_iter = 10;
+ struct beam_params *beam = NULL;
/* Long options */
const struct option longopts[] = {
@@ -256,6 +261,7 @@ int main(int argc, char *argv[])
{"input", 1, NULL, 'i'},
{"output", 1, NULL, 'o'},
{"geometry", 1, NULL, 'g'},
+ {"beam", 1, NULL, 'b'},
{"prefix", 1, NULL, 'x'},
{"basename", 0, &config_basename, 1},
{"no-check-prefix", 0, &config_checkprefix, 0},
@@ -265,7 +271,7 @@ int main(int argc, char *argv[])
};
/* Short options */
- while ((c = getopt_long(argc, argv, "hi:g:x:j:y:o:",
+ while ((c = getopt_long(argc, argv, "hi:g:x:j:y:o:b:",
longopts, NULL)) != -1)
{
@@ -302,6 +308,15 @@ int main(int argc, char *argv[])
n_iter = atoi(optarg);
break;
+ case 'b' :
+ beam = get_beam_parameters(optarg);
+ if ( beam == NULL ) {
+ ERROR("Failed to load beam parameters"
+ " from '%s'\n", optarg);
+ return 1;
+ }
+ break;
+
case 0 :
break;
@@ -348,6 +363,11 @@ int main(int argc, char *argv[])
}
free(geomfile);
+ if ( beam == NULL ) {
+ ERROR("You must provide a beam parameters file.\n");
+ return 1;
+ }
+
/* Prepare for iteration */
i_full = new_list_intensity();
obs = new_items();
@@ -388,13 +408,14 @@ int main(int argc, char *argv[])
snprintf(fnamereal, 1023, "%s%s", prefix, filename);
images[i].filename = fnamereal;
- images[i].div = 0.5e-3;
- images[i].bw = 0.001;
+ images[i].div = beam->divergence;
+ images[i].bw = beam->bandwidth;
images[i].orientation.w = 1.0;
images[i].orientation.x = 0.0;
images[i].orientation.y = 0.0;
images[i].orientation.z = 0.0;
images[i].det = det;
+ images[i].beam = beam;
/* Muppet proofing */
images[i].data = NULL;
diff --git a/src/geometry.c b/src/geometry.c
index cca2d050..2b94e7ba 100644
--- a/src/geometry.c
+++ b/src/geometry.c
@@ -15,18 +15,93 @@
#include <stdlib.h>
+#include <gsl/gsl_poly.h>
+#include <assert.h>
#include "utils.h"
#include "cell.h"
#include "image.h"
#include "peaks.h"
+#include "beam-parameters.h"
-#define MAX_CPEAKS (1024)
+#define MAX_CPEAKS (256 * 256)
+
+
+static signed int locate_peak(double x, double y, double z, double lambda,
+ struct detector *det, double *xdap, double *ydap)
+{
+ int p;
+ signed int found = -1;
+ const double den = 1.0/lambda + z;
+
+ for ( p=0; p<det->n_panels; p++ ) {
+
+ double xd, yd, cl;
+ double xda, yda;
+
+ /* Camera length for this panel */
+ cl = det->panels[p].clen;
+
+ /* Coordinates of peak relative to central beam, in m */
+ xd = cl * x / den;
+ yd = cl * y / den;
+
+ /* Convert to pixels */
+ xd *= det->panels[p].res;
+ yd *= det->panels[p].res;
+
+ /* Add the coordinates of the central beam */
+ xda = xd + det->panels[p].cx;
+ yda = yd + det->panels[p].cy;
+
+ /* Now, is this on this panel? */
+ if ( xda < det->panels[p].min_x ) continue;
+ if ( xda > det->panels[p].max_x ) continue;
+ if ( yda < det->panels[p].min_y ) continue;
+ if ( yda > det->panels[p].max_y ) continue;
+
+ /* If peak appears on multiple panels, reject it */
+ if ( found != -1 ) return -1;
+
+ /* Woohoo! */
+ found = p;
+ *xdap = xda;
+ *ydap = yda;
+
+ }
+
+ return found;
+}
+
+
+static double excitation_error(double xl, double yl, double zl,
+ double ds_sq, double lambda)
+{
+ double tt;
+ double a, b, c;
+ double r1, r2;
+ int n;
+
+ tt = angle_between(0.0, 0.0, 1.0, xl, yl, zl+1.0/lambda);
+
+ a = 1.0;
+ b = - cos(tt) * 2.0/lambda;
+ c = pow(lambda, -2.0) - ds_sq;
+
+ /* FIXME: I don't trust GSL's quadratic solver */
+ n = gsl_poly_solve_quadratic(a, b, c, &r1, &r2);
+ assert(n == 2);
+
+ r1 -= 1.0/lambda;
+ r2 -= 1.0/lambda;
+
+ if ( r1 > r2 ) return r2;
+ return r1;
+}
struct cpeak *find_intersections(struct image *image, UnitCell *cell,
- double divergence, double bandwidth,
int *n, int output)
{
double asx, asy, asz;
@@ -37,6 +112,11 @@ struct cpeak *find_intersections(struct image *image, UnitCell *cell,
int hmax, kmax, lmax;
double mres;
signed int h, k, l;
+ double bandwidth = image->bw;
+ double divergence = image->div;
+ double lambda = image->lambda;
+ const double profile_cutoff = 0.05e9; /* 0.1 nm^-1 */
+ double llow, lhigh; /* Wavelength */
cpeaks = malloc(sizeof(struct cpeak)*MAX_CPEAKS);
if ( cpeaks == NULL ) {
@@ -48,103 +128,91 @@ struct cpeak *find_intersections(struct image *image, UnitCell *cell,
&bsx, &bsy, &bsz,
&csx, &csy, &csz);
+ /* FIXME: Account for left-handed indexing */
+ asz = -asz; bsz = -bsz; csz = -csz;
+
mres = 1.0 / 8.0e-10; /* 8 Angstroms */
hmax = mres / modulus(asx, asy, asz);
kmax = mres / modulus(bsx, bsy, bsz);
lmax = mres / modulus(csx, csy, csz);
+ /* "low" gives the largest Ewald sphere,
+ * "high" gives the smallest Ewald sphere. */
+ llow = lambda - lambda*bandwidth/2.0;
+ lhigh = lambda + lambda*bandwidth/2.0;
+
for ( h=-hmax; h<hmax; h++ ) {
for ( k=-kmax; k<kmax; k++ ) {
for ( l=-lmax; l<lmax; l++ ) {
double xl, yl, zl;
- double ds_sq, dps_sq;
- double delta, divfact;
- double llow, lhigh;
- double xd, yd, cl;
+ double ds, ds_sq;
+ double rlow, rhigh; /* "Excitation error" */
+ signed int plow, phigh;
+ double xdalow, xdahigh;
+ double ydalow, ydahigh;
double xda, yda;
- int p;
- int found = 0;
+ /* Ignore central beam */
if ( (h==0) && (k==0) && (l==0) ) continue;
- llow = image->lambda - image->lambda*bandwidth/2.0;
- lhigh = image->lambda + image->lambda*bandwidth/2.0;
-
/* Get the coordinates of the reciprocal lattice point */
zl = h*asz + k*bsz + l*csz;
- if ( zl < 0.0 ) continue; /* Do this check very early */
+ if ( zl > 0.0 ) continue; /* Throw out if it's "in front" */
xl = h*asx + k*bsx + l*csx;
yl = h*asy + k*bsy + l*csy;
+ /* Calculate reciprocal lattice point modulus (and square) */
ds_sq = modulus_squared(xl, yl, zl); /* d*^2 */
- delta = divergence/image->lambda;
- dps_sq = ds_sq + pow(delta, 2.0); /* d'*^2 */
-
- /* In range? */
- divfact = 2.0 * delta * sqrt(xl*xl + yl*yl);
- if ( ds_sq - 2.0*zl/llow > 0.0 ) continue;
- if ( ds_sq - 2.0*zl/lhigh < 0.0 ) continue;
-
- /* Work out which panel this peak would fall on */
- for ( p=0; p<image->det->n_panels; p++ ) {
-
- /* Camera length for this panel */
- cl = image->det->panels[p].clen;
-
- /* Coordinates of peak relative to central beam, in m */
- xd = cl*xl / (ds_sq/(2.0*zl) - zl);
- yd = cl*yl / (ds_sq/(2.0*zl) - zl);
-
- /* Convert to pixels */
- xd *= image->det->panels[p].res;
- yd *= image->det->panels[p].res;
-
- /* Add the coordinates of the central beam */
- xda = xd + image->det->panels[p].cx;
- yda = yd + image->det->panels[p].cy;
-
- /* Now, is this on this panel? */
- if ( xda < image->det->panels[p].min_x ) continue;
- if ( xda > image->det->panels[p].max_x ) continue;
- if ( yda < image->det->panels[p].min_y ) continue;
- if ( yda > image->det->panels[p].max_y ) continue;
-
- /* Woohoo! */
- found = 1;
- break;
-
+ ds = sqrt(ds_sq);
+ if ( ds > mres ) continue; /* Outside resolution range */
+
+ /* Calculate excitation errors */
+ rlow = excitation_error(xl, yl, zl, ds_sq, llow);
+ rhigh = excitation_error(xl, yl, zl, ds_sq, lhigh);
+
+ if ( (fabs(rlow) > profile_cutoff)
+ && (fabs(rhigh) > profile_cutoff) ) {
+ /* Reflection is not close to Bragg at either of
+ * the two extremes of wavelength, so skip it. */
+ continue;
}
- if ( !found ) continue;
-
+ /* Locate peak on detector, and check it doesn't span panels */
+ plow = locate_peak(xl, yl, zl, llow, image->det,
+ &xdalow, &ydalow);
+ if ( plow == -1 ) continue;
+ phigh = locate_peak(xl, yl, zl, lhigh, image->det,
+ &xdahigh, &ydahigh);
+ if ( phigh == -1 ) continue;
+ if ( plow != phigh ) continue;
+
+ xda = xdahigh;
+ yda = ydahigh;
cpeaks[np].h = h;
cpeaks[np].k = k;
cpeaks[np].l = l;
- cpeaks[np].x = xda;
- cpeaks[np].y = yda;
+ cpeaks[np].x = xdahigh;
+ cpeaks[np].y = ydahigh;
np++;
if ( output ) {
- printf("%i %i %i 0.0 (at %f,%f)\n", h, k, l, xda, yda);
+ printf("%3i %3i %3i %6f (at %5.2f,%5.2f) %9e %9e\n",
+ h, k, l, 0.0, xda, yda, rlow, rhigh);
}
+ if ( np == MAX_CPEAKS ) goto out;
+
}
}
}
+out:
*n = np;
return cpeaks;
}
-/* Return the partiality of this reflection in this image */
-double partiality(struct image *image, signed int h, signed int k, signed int l)
-{
- return 1.0;
-}
-
-
double integrate_all(struct image *image, struct cpeak *cpeaks, int n)
{
double itot = 0.0;
diff --git a/src/geometry.h b/src/geometry.h
index 8ebfc1b2..0782a3e1 100644
--- a/src/geometry.h
+++ b/src/geometry.h
@@ -18,11 +18,8 @@
#endif
extern struct cpeak *find_intersections(struct image *image, UnitCell *cell,
- double divergence, double bandwidth,
int *n, int output);
-extern double partiality(struct image *image, signed int h,
- signed int k, signed int l);
extern double integrate_all(struct image *image, struct cpeak *cpeaks, int n);
diff --git a/src/image.h b/src/image.h
index 0f6db034..f6cb8a58 100644
--- a/src/image.h
+++ b/src/image.h
@@ -53,11 +53,21 @@ typedef struct _imagefeaturelist ImageFeatureList;
/* This structure represents a predicted peak in an image */
-struct cpeak {
+struct cpeak
+{
+ /* Indices */
signed int h;
signed int k;
signed int l;
+
double min_distance;
+
+ /* Partiality */
+ double r1;
+ double r2;
+ double p;
+
+ /* Location in image */
int x;
int y;
};
@@ -73,7 +83,7 @@ struct image {
UnitCell *candidate_cells[MAX_CELL_CANDIDATES];
int ncells;
struct detector *det;
- struct beam_params *beam;
+ struct beam_params *beam; /* The nominal beam parameters */
char *filename;
struct cpeak *cpeaks;
int n_cpeaks;
@@ -86,7 +96,7 @@ struct image {
double m; /* Mosaicity in radians */
- /* Information about the radiation */
+ /* Per-shot radiation values */
double lambda; /* Wavelength in m */
double div; /* Divergence in radians */
double bw; /* Bandwidth as a fraction */