diff options
author | Thomas White <taw@physics.org> | 2011-11-15 12:05:55 +0100 |
---|---|---|
committer | Thomas White <taw@physics.org> | 2012-02-22 15:27:40 +0100 |
commit | 38089071300b8e04ed42236dd08d9055094fb3b8 (patch) | |
tree | 91e1487ac820eb549e7652750867cd4fec039097 /src | |
parent | 404c612223dbfa0210902ebc5c9226927335aa65 (diff) |
Introduce "libcrystfel"
Diffstat (limited to 'src')
-rw-r--r-- | src/beam-parameters.c | 133 | ||||
-rw-r--r-- | src/beam-parameters.h | 40 | ||||
-rw-r--r-- | src/cell.c | 1164 | ||||
-rw-r--r-- | src/cell.h | 107 | ||||
-rw-r--r-- | src/detector.c | 1234 | ||||
-rw-r--r-- | src/detector.h | 131 | ||||
-rw-r--r-- | src/hdf5-file.c | 817 | ||||
-rw-r--r-- | src/hdf5-file.h | 55 | ||||
-rw-r--r-- | src/image.h | 8 | ||||
-rw-r--r-- | src/list_tmp.h | 106 | ||||
-rw-r--r-- | src/partial_sim.c | 2 | ||||
-rw-r--r-- | src/reflist.c | 1048 | ||||
-rw-r--r-- | src/reflist.h | 112 | ||||
-rw-r--r-- | src/scaling-report.c | 2 | ||||
-rw-r--r-- | src/thread-pool.c | 283 | ||||
-rw-r--r-- | src/thread-pool.h | 71 | ||||
-rw-r--r-- | src/utils.c | 488 | ||||
-rw-r--r-- | src/utils.h | 236 |
18 files changed, 6 insertions, 6031 deletions
diff --git a/src/beam-parameters.c b/src/beam-parameters.c deleted file mode 100644 index ac30ad04..00000000 --- a/src/beam-parameters.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * beam-parameters.c - * - * Beam parameters - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> - -#include "beam-parameters.h" -#include "utils.h" - - -struct beam_params *get_beam_parameters(const char *filename) -{ - FILE *fh; - struct beam_params *b; - char *rval; - int reject; - - fh = fopen(filename, "r"); - if ( fh == NULL ) return NULL; - - b = calloc(1, sizeof(struct beam_params)); - if ( b == NULL ) return NULL; - - b->fluence = -1.0; - b->beam_radius = -1.0; - b->photon_energy = -1.0; - b->bandwidth = -1.0; - b->divergence = -1.0; - b->dqe = -1.0; - b->adu_per_photon = -1.0; - - do { - - int n1; - char line[1024]; - int i; - char **bits; - - rval = fgets(line, 1023, fh); - if ( rval == NULL ) break; - chomp(line); - - n1 = assplode(line, " \t", &bits, ASSPLODE_NONE); - if ( n1 < 3 ) { - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - continue; - } - - if ( bits[1][0] != '=' ) { - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - continue; - } - - if ( strcmp(bits[0], "beam/fluence") == 0 ) { - b->fluence = atof(bits[2]); - } else if ( strcmp(bits[0], "beam/radius") == 0 ) { - b->beam_radius = atof(bits[2]); - } else if ( strcmp(bits[0], "beam/photon_energy") == 0 ) { - b->photon_energy = atof(bits[2]); - } else if ( strcmp(bits[0], "beam/bandwidth") == 0 ) { - b->bandwidth = atof(bits[2]); - } else if ( strcmp(bits[0], "beam/divergence") == 0 ) { - b->divergence = atof(bits[2]); - } else if ( strcmp(bits[0], "detector/dqe") == 0 ) { - b->dqe = atof(bits[2]); - } else if ( strcmp(bits[0], "detector/adu_per_photon") == 0 ) { - b->adu_per_photon = atof(bits[2]); - } else { - ERROR("Unrecognised field '%s'\n", bits[0]); - } - - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - - } while ( rval != NULL ); - fclose(fh); - - reject = 0; - - if ( b->fluence < 0.0 ) { - ERROR("Invalid or unspecified value for 'beam/fluence'.\n"); - reject = 1; - } - if ( b->beam_radius < 0.0 ) { - ERROR("Invalid or unspecified value for 'beam/radius'.\n"); - reject = 1; - } - if ( b->photon_energy < 0.0 ) { - ERROR("Invalid or unspecified value for" - " 'beam/photon_energy'.\n"); - reject = 1; - } - if ( b->bandwidth < 0.0 ) { - ERROR("Invalid or unspecified value for 'beam/bandwidth'.\n"); - reject = 1; - } - if ( b->divergence < 0.0 ) { - ERROR("Invalid or unspecified value for 'beam/divergence'.\n"); - reject = 1; - } - if ( b->dqe < 0.0 ) { - ERROR("Invalid or unspecified value for 'detector/dqe'.\n"); - reject = 1; - } - if ( b->adu_per_photon < 0.0 ) { - ERROR("Invalid or unspecified value for" - " 'detector/adu_per_photon'.\n"); - reject = 1; - } - - if ( reject ) { - ERROR("Please fix the above problems with the beam" - " parameters file and try again.\n"); - return NULL; - } - - return b; -} diff --git a/src/beam-parameters.h b/src/beam-parameters.h deleted file mode 100644 index 411ab449..00000000 --- a/src/beam-parameters.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * beam-parameters.h - * - * Beam parameters - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#ifndef BEAM_PARAMETERS_H -#define BEAM_PARAMETERS_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -struct beam_params -{ - double fluence; /* photons per pulse */ - double beam_radius; /* metres */ - double photon_energy; /* eV per photon */ - double bandwidth; /* FWHM(wavelength) over wavelength. - * Note: current simulation code just uses - * a rectangular distribution with this as - * its (full) width. */ - double divergence; /* divergence (radians) */ - - double dqe; /* Detector DQE (fraction) */ - double adu_per_photon; /* Detector "gain" */ -}; - - -extern struct beam_params *get_beam_parameters(const char *filename); - - -#endif /* BEAM_PARAMETERS_H */ diff --git a/src/cell.c b/src/cell.c deleted file mode 100644 index c31697bc..00000000 --- a/src/cell.c +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * cell.c - * - * Unit Cell Calculations - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <math.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <gsl/gsl_matrix.h> -#include <gsl/gsl_blas.h> -#include <gsl/gsl_linalg.h> - -#include "cell.h" -#include "utils.h" -#include "image.h" - - -/** - * SECTION:unitcell - * @short_description: Unit cell - * @title: UnitCell - * @section_id: - * @see_also: - * @include: "cell.h" - * @Image: - * - * This structure represents a unit cell. - */ - - - -/* Weighting factor of lengths relative to angles */ -#define LWEIGHT (10.0e-9) - -typedef enum { - CELL_REP_CRYST, - CELL_REP_CART, - CELL_REP_RECIP -} CellRepresentation; - -struct _unitcell { - - CellRepresentation rep; - - /* Crystallographic representation */ - double a; /* m */ - double b; /* m */ - double c; /* m */ - double alpha; /* Radians */ - double beta; /* Radians */ - double gamma; /* Radians */ - - /* Cartesian representation */ - double ax; double bx; double cx; - double ay; double by; double cy; - double az; double bz; double cz; - - /* Cartesian representation of reciprocal axes */ - double axs; double bxs; double cxs; - double ays; double bys; double cys; - double azs; double bzs; double czs; - - char *pointgroup; - char *spacegroup; -}; - - -/************************** Setters and Constructors **************************/ - - -/** - * cell_new: - * - * Create a new %UnitCell. - * - * Returns: the new unit cell, or NULL on failure. - * - */ -UnitCell *cell_new() -{ - UnitCell *cell; - - cell = malloc(sizeof(UnitCell)); - if ( cell == NULL ) return NULL; - - cell->a = 1.0; - cell->b = 1.0; - cell->c = 1.0; - cell->alpha = M_PI_2; - cell->beta = M_PI_2; - cell->gamma = M_PI_2; - - cell->rep = CELL_REP_CRYST; - - cell->pointgroup = strdup("1"); - cell->spacegroup = strdup("P 1"); - - return cell; -} - - -/** - * cell_free: - * @cell: A %UnitCell to free. - * - * Frees a %UnitCell, and all internal resources concerning that cell. - * - */ -void cell_free(UnitCell *cell) -{ - if ( cell == NULL ) return; - free(cell->pointgroup); - free(cell->spacegroup); - free(cell); -} - - -void cell_set_parameters(UnitCell *cell, double a, double b, double c, - double alpha, double beta, double gamma) -{ - if ( cell == NULL ) return; - - cell->a = a; - cell->b = b; - cell->c = c; - cell->alpha = alpha; - cell->beta = beta; - cell->gamma = gamma; - - cell->rep = CELL_REP_CRYST; -} - - -void cell_set_cartesian(UnitCell *cell, - double ax, double ay, double az, - double bx, double by, double bz, - double cx, double cy, double cz) -{ - if ( cell == NULL ) return; - - cell->ax = ax; cell->ay = ay; cell->az = az; - cell->bx = bx; cell->by = by; cell->bz = bz; - cell->cx = cx; cell->cy = cy; cell->cz = cz; - - cell->rep = CELL_REP_CART; -} - - -void cell_set_cartesian_a(UnitCell *cell, double ax, double ay, double az) -{ - if ( cell == NULL ) return; - cell->ax = ax; cell->ay = ay; cell->az = az; - cell->rep = CELL_REP_CART; -} - - -void cell_set_cartesian_b(UnitCell *cell, double bx, double by, double bz) -{ - if ( cell == NULL ) return; - cell->bx = bx; cell->by = by; cell->bz = bz; - cell->rep = CELL_REP_CART; -} - - -void cell_set_cartesian_c(UnitCell *cell, double cx, double cy, double cz) -{ - if ( cell == NULL ) return; - cell->cx = cx; cell->cy = cy; cell->cz = cz; - cell->rep = CELL_REP_CART; -} - - -UnitCell *cell_new_from_parameters(double a, double b, double c, - double alpha, double beta, double gamma) -{ - UnitCell *cell; - - cell = cell_new(); - if ( cell == NULL ) return NULL; - - cell_set_parameters(cell, a, b, c, alpha, beta, gamma); - - return cell; -} - - -UnitCell *cell_new_from_reciprocal_axes(struct rvec as, struct rvec bs, - struct rvec cs) -{ - UnitCell *cell; - - cell = cell_new(); - if ( cell == NULL ) return NULL; - - cell->axs = as.u; cell->ays = as.v; cell->azs = as.w; - cell->bxs = bs.u; cell->bys = bs.v; cell->bzs = bs.w; - cell->cxs = cs.u; cell->cys = cs.v; cell->czs = cs.w; - - cell->rep = CELL_REP_RECIP; - - return cell; -} - - -UnitCell *cell_new_from_direct_axes(struct rvec a, struct rvec b, struct rvec c) -{ - UnitCell *cell; - - cell = cell_new(); - if ( cell == NULL ) return NULL; - - cell->ax = a.u; cell->ay = a.v; cell->az = a.w; - cell->bx = b.u; cell->by = b.v; cell->bz = b.w; - cell->cx = c.u; cell->cy = c.v; cell->cz = c.w; - - cell->rep = CELL_REP_CART; - - return cell; -} - - -UnitCell *cell_new_from_cell(UnitCell *orig) -{ - UnitCell *new; - double ax, ay, az, bx, by, bz, cx, cy, cz; - - new = cell_new(); - - cell_get_cartesian(orig, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); - cell_set_cartesian(new, ax, ay, az, bx, by, bz, cx, cy, cz); - cell_set_pointgroup(new, orig->pointgroup); - cell_set_spacegroup(new, orig->spacegroup); - - return new; -} - - -void cell_set_reciprocal(UnitCell *cell, - double asx, double asy, double asz, - double bsx, double bsy, double bsz, - double csx, double csy, double csz) -{ - if ( cell == NULL ) return; - - cell->axs = asx; cell->ays = asy; cell->azs = asz; - cell->bxs = bsx; cell->bys = bsy; cell->bzs = bsz; - cell->cxs = csx; cell->cys = csy; cell->czs = csz; - - cell->rep = CELL_REP_RECIP; -} - - -void cell_set_spacegroup(UnitCell *cell, const char *sym) -{ - free(cell->spacegroup); - cell->spacegroup = strdup(sym); -} - - -void cell_set_pointgroup(UnitCell *cell, const char *sym) -{ - free(cell->pointgroup); - cell->pointgroup = strdup(sym); -} - - -/************************* Getter helper functions ****************************/ - -static int cell_crystallographic_to_cartesian(UnitCell *cell, - double *ax, double *ay, double *az, - double *bx, double *by, double *bz, - double *cx, double *cy, double *cz) -{ - double tmp, V, cosalphastar, cstar; - - /* Firstly: Get a in terms of x, y and z - * +a (cryst) is defined to lie along +x (cart) */ - *ax = cell->a; - *ay = 0.0; - *az = 0.0; - - /* b in terms of x, y and z - * b (cryst) is defined to lie in the xy (cart) plane */ - *bx = cell->b*cos(cell->gamma); - *by = cell->b*sin(cell->gamma); - *bz = 0.0; - - tmp = cos(cell->alpha)*cos(cell->alpha) - + cos(cell->beta)*cos(cell->beta) - + cos(cell->gamma)*cos(cell->gamma) - - 2.0*cos(cell->alpha)*cos(cell->beta)*cos(cell->gamma); - V = cell->a * cell->b * cell->c * sqrt(1.0 - tmp); - - cosalphastar = cos(cell->beta)*cos(cell->gamma) - cos(cell->alpha); - cosalphastar /= sin(cell->beta)*sin(cell->gamma); - - cstar = (cell->a * cell->b * sin(cell->gamma))/V; - - /* c in terms of x, y and z */ - *cx = cell->c*cos(cell->beta); - *cy = -cell->c*sin(cell->beta)*cosalphastar; - *cz = 1.0/cstar; - - return 0; -} - - -/* Why yes, I do enjoy long argument lists...! */ -static int cell_invert(double ax, double ay, double az, - double bx, double by, double bz, - double cx, double cy, double cz, - double *asx, double *asy, double *asz, - double *bsx, double *bsy, double *bsz, - double *csx, double *csy, double *csz) -{ - int s; - gsl_matrix *m; - gsl_matrix *inv; - gsl_permutation *perm; - - m = gsl_matrix_alloc(3, 3); - if ( m == NULL ) { - ERROR("Couldn't allocate memory for matrix\n"); - return 1; - } - gsl_matrix_set(m, 0, 0, ax); - gsl_matrix_set(m, 0, 1, bx); - gsl_matrix_set(m, 0, 2, cx); - gsl_matrix_set(m, 1, 0, ay); - gsl_matrix_set(m, 1, 1, by); - gsl_matrix_set(m, 1, 2, cy); - gsl_matrix_set(m, 2, 0, az); - gsl_matrix_set(m, 2, 1, bz); - gsl_matrix_set(m, 2, 2, cz); - - /* Invert */ - perm = gsl_permutation_alloc(m->size1); - if ( perm == NULL ) { - ERROR("Couldn't allocate permutation\n"); - gsl_matrix_free(m); - return 1; - } - inv = gsl_matrix_alloc(m->size1, m->size2); - if ( inv == NULL ) { - ERROR("Couldn't allocate inverse\n"); - gsl_matrix_free(m); - gsl_permutation_free(perm); - return 1; - } - if ( gsl_linalg_LU_decomp(m, perm, &s) ) { - ERROR("Couldn't decompose matrix\n"); - gsl_matrix_free(m); - gsl_permutation_free(perm); - return 1; - } - if ( gsl_linalg_LU_invert(m, perm, inv) ) { - ERROR("Couldn't invert matrix\n"); - gsl_matrix_free(m); - gsl_permutation_free(perm); - return 1; - } - gsl_permutation_free(perm); - gsl_matrix_free(m); - - /* Transpose */ - gsl_matrix_transpose(inv); - - *asx = gsl_matrix_get(inv, 0, 0); - *bsx = gsl_matrix_get(inv, 0, 1); - *csx = gsl_matrix_get(inv, 0, 2); - *asy = gsl_matrix_get(inv, 1, 0); - *bsy = gsl_matrix_get(inv, 1, 1); - *csy = gsl_matrix_get(inv, 1, 2); - *asz = gsl_matrix_get(inv, 2, 0); - *bsz = gsl_matrix_get(inv, 2, 1); - *csz = gsl_matrix_get(inv, 2, 2); - - gsl_matrix_free(inv); - - return 0; -} - - -/********************************** Getters ***********************************/ - -int cell_get_parameters(UnitCell *cell, double *a, double *b, double *c, - double *alpha, double *beta, double *gamma) -{ - double ax, ay, az, bx, by, bz, cx, cy, cz; - - if ( cell == NULL ) return 1; - - switch ( cell->rep ) { - - case CELL_REP_CRYST: - /* Direct response */ - *a = cell->a; - *b = cell->b; - *c = cell->c; - *alpha = cell->alpha; - *beta = cell->beta; - *gamma = cell->gamma; - return 0; - - case CELL_REP_CART: - /* Convert cartesian -> crystallographic */ - *a = modulus(cell->ax, cell->ay, cell->az); - *b = modulus(cell->bx, cell->by, cell->bz); - *c = modulus(cell->cx, cell->cy, cell->cz); - - *alpha = angle_between(cell->bx, cell->by, cell->bz, - cell->cx, cell->cy, cell->cz); - *beta = angle_between(cell->ax, cell->ay, cell->az, - cell->cx, cell->cy, cell->cz); - *gamma = angle_between(cell->ax, cell->ay, cell->az, - cell->bx, cell->by, cell->bz); - return 0; - - case CELL_REP_RECIP: - /* Convert reciprocal -> crystallographic. - * Start by converting reciprocal -> cartesian */ - cell_invert(cell->axs, cell->ays, cell->azs, - cell->bxs, cell->bys, cell->bzs, - cell->cxs, cell->cys, cell->czs, - &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); - - /* Now convert cartesian -> crystallographic */ - *a = modulus(ax, ay, az); - *b = modulus(bx, by, bz); - *c = modulus(cx, cy, cz); - - *alpha = angle_between(bx, by, bz, cx, cy, cz); - *beta = angle_between(ax, ay, az, cx, cy, cz); - *gamma = angle_between(ax, ay, az, bx, by, bz); - return 0; - } - - return 1; -} - - -int cell_get_cartesian(UnitCell *cell, - double *ax, double *ay, double *az, - double *bx, double *by, double *bz, - double *cx, double *cy, double *cz) -{ - if ( cell == NULL ) return 1; - - switch ( cell->rep ) { - - case CELL_REP_CRYST: - /* Convert crystallographic -> cartesian. */ - return cell_crystallographic_to_cartesian(cell, - ax, ay, az, - bx, by, bz, - cx, cy, cz); - - case CELL_REP_CART: - /* Direct response */ - *ax = cell->ax; *ay = cell->ay; *az = cell->az; - *bx = cell->bx; *by = cell->by; *bz = cell->bz; - *cx = cell->cx; *cy = cell->cy; *cz = cell->cz; - return 0; - - case CELL_REP_RECIP: - /* Convert reciprocal -> cartesian */ - return cell_invert(cell->axs, cell->ays, cell->azs, - cell->bxs, cell->bys, cell->bzs, - cell->cxs, cell->cys, cell->czs, - ax, ay, az, bx, by, bz, cx, cy, cz); - - } - - return 1; -} - - -int cell_get_reciprocal(UnitCell *cell, - double *asx, double *asy, double *asz, - double *bsx, double *bsy, double *bsz, - double *csx, double *csy, double *csz) -{ - int r; - double ax, ay, az, bx, by, bz, cx, cy, cz; - if ( cell == NULL ) return 1; - - switch ( cell->rep ) { - - case CELL_REP_CRYST: - /* Convert crystallographic -> reciprocal */ - r = cell_crystallographic_to_cartesian(cell, - &ax, &ay, &az, - &bx, &by, &bz, - &cx, &cy, &cz); - if ( r ) return r; - return cell_invert(ax, ay, az,bx, by, bz, cx, cy, cz, - asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); - - case CELL_REP_CART: - /* Convert cartesian -> reciprocal */ - cell_invert(cell->ax, cell->ay, cell->az, - cell->bx, cell->by, cell->bz, - cell->cx, cell->cy, cell->cz, - asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); - return 0; - - case CELL_REP_RECIP: - /* Direct response */ - *asx = cell->axs; *asy = cell->ays; *asz = cell->azs; - *bsx = cell->bxs; *bsy = cell->bys; *bsz = cell->bzs; - *csx = cell->cxs; *csy = cell->cys; *csz = cell->czs; - return 0; - - } - - return 1; -} - - -const char *cell_get_pointgroup(UnitCell *cell) -{ - return cell->pointgroup; -} - - -const char *cell_get_spacegroup(UnitCell *cell) -{ - return cell->spacegroup; -} - - - - - -/********************************* Utilities **********************************/ - -static const char *cell_rep(UnitCell *cell) -{ - switch ( cell->rep ) { - case CELL_REP_CRYST: - return "crystallographic, direct space"; - case CELL_REP_CART: - return "cartesian, direct space"; - case CELL_REP_RECIP: - return "cartesian, reciprocal space"; - } - - return "unknown"; -} - - -/** - * cell_rotate: - * @in: A %UnitCell to rotate - * @quat: A %quaternion - * - * Rotate a %UnitCell using a %quaternion. - * - * Returns: a newly allocated rotated copy of @in. - * - */ -UnitCell *cell_rotate(UnitCell *in, struct quaternion quat) -{ - struct rvec a, b, c; - struct rvec an, bn, cn; - UnitCell *out = cell_new_from_cell(in); - - cell_get_cartesian(in, &a.u, &a.v, &a.w, - &b.u, &b.v, &b.w, - &c.u, &c.v, &c.w); - - an = quat_rot(a, quat); - bn = quat_rot(b, quat); - cn = quat_rot(c, quat); - - cell_set_cartesian(out, an.u, an.v, an.w, - bn.u, bn.v, bn.w, - cn.u, cn.v, cn.w); - - return out; -} - - -void cell_print(UnitCell *cell) -{ - double asx, asy, asz; - double bsx, bsy, bsz; - double csx, csy, csz; - double a, b, c, alpha, beta, gamma; - double ax, ay, az, bx, by, bz, cx, cy, cz; - - cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma); - - STATUS(" a b c alpha beta gamma\n"); - STATUS("%5.2f %5.2f %5.2f nm %6.2f %6.2f %6.2f deg\n", - a*1e9, b*1e9, c*1e9, - rad2deg(alpha), rad2deg(beta), rad2deg(gamma)); - - cell_get_cartesian(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz); - - STATUS("a = %10.3e %10.3e %10.3e m\n", ax, ay, az); - STATUS("b = %10.3e %10.3e %10.3e m\n", bx, by, bz); - STATUS("c = %10.3e %10.3e %10.3e m\n", cx, cy, cz); - - cell_get_reciprocal(cell, &asx, &asy, &asz, - &bsx, &bsy, &bsz, - &csx, &csy, &csz); - - STATUS("astar = %10.3e %10.3e %10.3e m^-1 (modulus = %10.3e m^-1)\n", - asx, asy, asz, modulus(asx, asy, asz)); - STATUS("bstar = %10.3e %10.3e %10.3e m^-1 (modulus = %10.3e m^-1)\n", - bsx, bsy, bsz, modulus(bsx, bsy, bsz)); - STATUS("cstar = %10.3e %10.3e %10.3e m^-1 (modulus = %10.3e m^-1)\n", - csx, csy, csz, modulus(csx, csy, csz)); - - STATUS("Point group: %s\n", cell_get_pointgroup(cell)); - STATUS("Cell representation is %s.\n", cell_rep(cell)); -} - - -#define MAX_CAND (1024) - -static int right_handed(struct rvec a, struct rvec b, struct rvec c) -{ - struct rvec aCb; - double aCb_dot_c; - - /* "a" cross "b" */ - aCb.u = a.v*b.w - a.w*b.v; - aCb.v = - (a.u*b.w - a.w*b.u); - aCb.w = a.u*b.v - a.v*b.u; - - /* "a cross b" dot "c" */ - aCb_dot_c = aCb.u*c.u + aCb.v*c.v + aCb.w*c.w; - - if ( aCb_dot_c > 0.0 ) return 1; - return 0; -} - - -struct cvec { - struct rvec vec; - float na; - float nb; - float nc; - float fom; -}; - - -static int same_vector(struct cvec a, struct cvec b) -{ - if ( a.na != b.na ) return 0; - if ( a.nb != b.nb ) return 0; - if ( a.nc != b.nc ) return 0; - return 1; -} - - -/* Attempt to make 'cell' fit into 'template' somehow */ -UnitCell *match_cell(UnitCell *cell, UnitCell *template, int verbose, - int reduce) -{ - signed int n1l, n2l, n3l; - double asx, asy, asz; - double bsx, bsy, bsz; - double csx, csy, csz; - int i, j; - double lengths[3]; - double angles[3]; - struct cvec *cand[3]; - UnitCell *new_cell = NULL; - float best_fom = +999999999.9; /* Large number.. */ - int ncand[3] = {0,0,0}; - signed int ilow, ihigh; - float ltl = 5.0; /* percent */ - float angtol = deg2rad(1.5); - - if ( cell_get_reciprocal(template, &asx, &asy, &asz, - &bsx, &bsy, &bsz, - &csx, &csy, &csz) ) { - ERROR("Couldn't get reciprocal cell for template.\n"); - return NULL; - } - - lengths[0] = modulus(asx, asy, asz); - lengths[1] = modulus(bsx, bsy, bsz); - lengths[2] = modulus(csx, csy, csz); - - angles[0] = angle_between(bsx, bsy, bsz, csx, csy, csz); - angles[1] = angle_between(asx, asy, asz, csx, csy, csz); - angles[2] = angle_between(asx, asy, asz, bsx, bsy, bsz); - - cand[0] = malloc(MAX_CAND*sizeof(struct cvec)); - cand[1] = malloc(MAX_CAND*sizeof(struct cvec)); - cand[2] = malloc(MAX_CAND*sizeof(struct cvec)); - - if ( cell_get_reciprocal(cell, &asx, &asy, &asz, - &bsx, &bsy, &bsz, - &csx, &csy, &csz) ) { - ERROR("Couldn't get reciprocal cell.\n"); - return NULL; - } - - if ( reduce ) { - ilow = -2; ihigh = 4; - } else { - ilow = 0; ihigh = 1; - } - - /* Negative values mean 1/n, positive means n, zero means zero */ - for ( n1l=ilow; n1l<=ihigh; n1l++ ) { - for ( n2l=ilow; n2l<=ihigh; n2l++ ) { - for ( n3l=ilow; n3l<=ihigh; n3l++ ) { - - float n1, n2, n3; - signed int b1, b2, b3; - - n1 = (n1l>=0) ? (n1l) : (1.0/n1l); - n2 = (n2l>=0) ? (n2l) : (1.0/n2l); - n3 = (n3l>=0) ? (n3l) : (1.0/n3l); - - if ( !reduce ) { - if ( n1l + n2l + n3l > 1 ) continue; - } - - /* 'bit' values can be +1 or -1 */ - for ( b1=-1; b1<=1; b1+=2 ) { - for ( b2=-1; b2<=1; b2+=2 ) { - for ( b3=-1; b3<=1; b3+=2 ) { - - double tx, ty, tz; - double tlen; - int i; - - n1 *= b1; n2 *= b2; n3 *= b3; - - tx = n1*asx + n2*bsx + n3*csx; - ty = n1*asy + n2*bsy + n3*csy; - tz = n1*asz + n2*bsz + n3*csz; - tlen = modulus(tx, ty, tz); - - /* Test modulus for agreement with moduli of template */ - for ( i=0; i<3; i++ ) { - - if ( !within_tolerance(lengths[i], tlen, ltl) ) - continue; - - cand[i][ncand[i]].vec.u = tx; - cand[i][ncand[i]].vec.v = ty; - cand[i][ncand[i]].vec.w = tz; - cand[i][ncand[i]].na = n1; - cand[i][ncand[i]].nb = n2; - cand[i][ncand[i]].nc = n3; - cand[i][ncand[i]].fom = fabs(lengths[i] - tlen); - if ( ncand[i] == MAX_CAND ) { - ERROR("Too many candidates\n"); - } else { - ncand[i]++; - } - } - - } - } - } - - } - } - } - - if ( verbose ) { - STATUS("Candidates: %i %i %i\n", ncand[0], ncand[1], ncand[2]); - } - - for ( i=0; i<ncand[0]; i++ ) { - for ( j=0; j<ncand[1]; j++ ) { - - double ang; - int k; - float fom1; - - if ( same_vector(cand[0][i], cand[1][j]) ) continue; - - /* Measure the angle between the ith candidate for axis 0 - * and the jth candidate for axis 1 */ - ang = angle_between(cand[0][i].vec.u, cand[0][i].vec.v, - cand[0][i].vec.w, cand[1][j].vec.u, - cand[1][j].vec.v, cand[1][j].vec.w); - - /* Angle between axes 0 and 1 should be angle 2 */ - if ( fabs(ang - angles[2]) > angtol ) continue; - - fom1 = fabs(ang - angles[2]); - - for ( k=0; k<ncand[2]; k++ ) { - - float fom2, fom3; - - if ( same_vector(cand[1][j], cand[2][k]) ) continue; - - /* Measure the angle between the current candidate for - * axis 0 and the kth candidate for axis 2 */ - ang = angle_between(cand[0][i].vec.u, cand[0][i].vec.v, - cand[0][i].vec.w, cand[2][k].vec.u, - cand[2][k].vec.v, cand[2][k].vec.w); - - /* ... it should be angle 1 ... */ - if ( fabs(ang - angles[1]) > angtol ) continue; - - fom2 = fom1 + fabs(ang - angles[1]); - - /* Finally, the angle between the current candidate for - * axis 1 and the kth candidate for axis 2 */ - ang = angle_between(cand[1][j].vec.u, cand[1][j].vec.v, - cand[1][j].vec.w, cand[2][k].vec.u, - cand[2][k].vec.v, cand[2][k].vec.w); - - /* ... it should be angle 0 ... */ - if ( fabs(ang - angles[0]) > angtol ) continue; - - /* Unit cell must be right-handed */ - if ( !right_handed(cand[0][i].vec, cand[1][j].vec, - cand[2][k].vec) ) continue; - - fom3 = fom2 + fabs(ang - angles[0]); - fom3 += LWEIGHT * (cand[0][i].fom + cand[1][j].fom - + cand[2][k].fom); - - if ( fom3 < best_fom ) { - if ( new_cell != NULL ) free(new_cell); - new_cell = cell_new_from_reciprocal_axes( - cand[0][i].vec, cand[1][j].vec, - cand[2][k].vec); - best_fom = fom3; - } - - } - - } - } - - free(cand[0]); - free(cand[1]); - free(cand[2]); - - return new_cell; -} - - - -UnitCell *match_cell_ab(UnitCell *cell, UnitCell *template) -{ - double ax, ay, az; - double bx, by, bz; - double cx, cy, cz; - int i; - double lengths[3]; - int used[3]; - struct rvec real_a, real_b, real_c; - struct rvec params[3]; - double alen, blen, clen; - float ltl = 5.0; /* percent */ - int have_real_a; - int have_real_b; - int have_real_c; - - /* Get the lengths to match */ - if ( cell_get_cartesian(template, &ax, &ay, &az, - &bx, &by, &bz, - &cx, &cy, &cz) ) - { - ERROR("Couldn't get cell for template.\n"); - return NULL; - } - alen = modulus(ax, ay, az); - blen = modulus(bx, by, bz); - clen = modulus(cx, cy, cz); - - /* Get the lengths from the cell and turn them into anonymous vectors */ - if ( cell_get_cartesian(cell, &ax, &ay, &az, - &bx, &by, &bz, - &cx, &cy, &cz) ) - { - ERROR("Couldn't get cell.\n"); - return NULL; - } - lengths[0] = modulus(ax, ay, az); - lengths[1] = modulus(bx, by, bz); - lengths[2] = modulus(cx, cy, cz); - used[0] = 0; used[1] = 0; used[2] = 0; - params[0].u = ax; params[0].v = ay; params[0].w = az; - params[1].u = bx; params[1].v = by; params[1].w = bz; - params[2].u = cx; params[2].v = cy; params[2].w = cz; - - real_a.u = 0.0; real_a.v = 0.0; real_a.w = 0.0; - real_b.u = 0.0; real_b.v = 0.0; real_b.w = 0.0; - real_c.u = 0.0; real_c.v = 0.0; real_c.w = 0.0; - - /* Check each vector against a and b */ - have_real_a = 0; - have_real_b = 0; - for ( i=0; i<3; i++ ) { - if ( within_tolerance(lengths[i], alen, ltl) - && !used[i] && !have_real_a ) - { - used[i] = 1; - memcpy(&real_a, ¶ms[i], sizeof(struct rvec)); - have_real_a = 1; - } - if ( within_tolerance(lengths[i], blen, ltl) - && !used[i] && !have_real_b ) - { - used[i] = 1; - memcpy(&real_b, ¶ms[i], sizeof(struct rvec)); - have_real_b = 1; - } - } - - /* Have we matched both a and b? */ - if ( !(have_real_a && have_real_b) ) return NULL; - - /* "c" is "the other one" */ - have_real_c = 0; - for ( i=0; i<3; i++ ) { - if ( !used[i] ) { - memcpy(&real_c, ¶ms[i], sizeof(struct rvec)); - have_real_c = 1; - } - } - - if ( !have_real_c ) { - ERROR("Huh? Couldn't find the third vector.\n"); - ERROR("Matches: %i %i %i\n", used[0], used[1], used[2]); - return NULL; - } - - /* Flip c if not right-handed */ - if ( !right_handed(real_a, real_b, real_c) ) { - real_c.u = -real_c.u; - real_c.v = -real_c.v; - real_c.w = -real_c.w; - } - - return cell_new_from_direct_axes(real_a, real_b, real_c); -} - - -/* Return sin(theta)/lambda = 1/2d. Multiply by two if you want 1/d */ -double resolution(UnitCell *cell, signed int h, signed int k, signed int l) -{ - double a, b, c, alpha, beta, gamma; - - cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma); - - const double Vsq = a*a*b*b*c*c*(1 - cos(alpha)*cos(alpha) - - cos(beta)*cos(beta) - - cos(gamma)*cos(gamma) - + 2*cos(alpha)*cos(beta)*cos(gamma) ); - - const double S11 = b*b*c*c*sin(alpha)*sin(alpha); - const double S22 = a*a*c*c*sin(beta)*sin(beta); - const double S33 = a*a*b*b*sin(gamma)*sin(gamma); - const double S12 = a*b*c*c*(cos(alpha)*cos(beta) - cos(gamma)); - const double S23 = a*a*b*c*(cos(beta)*cos(gamma) - cos(alpha)); - const double S13 = a*b*b*c*(cos(gamma)*cos(alpha) - cos(beta)); - - const double brackets = S11*h*h + S22*k*k + S33*l*l - + 2*S12*h*k + 2*S23*k*l + 2*S13*h*l; - const double oneoverdsq = brackets / Vsq; - const double oneoverd = sqrt(oneoverdsq); - - return oneoverd / 2; -} - - -static void cell_set_pointgroup_from_pdb(UnitCell *cell, const char *sym) -{ - char *new = NULL; - - if ( strcmp(sym, "P 1") == 0 ) new = "1"; - if ( strcmp(sym, "P 63") == 0 ) new = "6"; - if ( strcmp(sym, "P 21 21 21") == 0 ) new = "222"; - if ( strcmp(sym, "P 2 2 2") == 0 ) new = "222"; - if ( strcmp(sym, "P 43 21 2") == 0 ) new = "422"; - - if ( new != NULL ) { - cell_set_pointgroup(cell, new); - } else { - ERROR("Can't determine point group for '%s'\n", sym); - } -} - - -UnitCell *load_cell_from_pdb(const char *filename) -{ - FILE *fh; - char *rval; - UnitCell *cell = NULL; - - fh = fopen(filename, "r"); - if ( fh == NULL ) { - ERROR("Couldn't open '%s'\n", filename); - return NULL; - } - - do { - - char line[1024]; - - rval = fgets(line, 1023, fh); - - if ( strncmp(line, "CRYST1", 6) == 0 ) { - - float a, b, c, al, be, ga; - char as[10], bs[10], cs[10]; - char als[8], bes[8], gas[8]; - char *sym; - int r; - - memcpy(as, line+6, 9); as[9] = '\0'; - memcpy(bs, line+15, 9); bs[9] = '\0'; - memcpy(cs, line+24, 9); cs[9] = '\0'; - memcpy(als, line+33, 7); als[7] = '\0'; - memcpy(bes, line+40, 7); bes[7] = '\0'; - memcpy(gas, line+47, 7); gas[7] = '\0'; - - r = sscanf(as, "%f", &a); - r += sscanf(bs, "%f", &b); - r += sscanf(cs, "%f", &c); - r += sscanf(als, "%f", &al); - r += sscanf(bes, "%f", &be); - r += sscanf(gas, "%f", &ga); - - if ( r != 6 ) { - STATUS("Couldn't understand CRYST1 line.\n"); - continue; - } - - cell = cell_new_from_parameters(a*1e-10, - b*1e-10, c*1e-10, - deg2rad(al), - deg2rad(be), - deg2rad(ga)); - - if ( strlen(line) > 65 ) { - sym = strndup(line+55, 10); - notrail(sym); - cell_set_pointgroup_from_pdb(cell, sym); - cell_set_spacegroup(cell, sym); - free(sym); - } else { - cell_set_pointgroup_from_pdb(cell, "P 1"); - cell_set_spacegroup(cell, "P 1"); - ERROR("CRYST1 line without space group.\n"); - } - - break; /* Done */ - } - - } while ( rval != NULL ); - - fclose(fh); - - return cell; -} - - -#ifdef GSL_FUDGE -/* Force the linker to bring in CBLAS to make GSL happy */ -void cell_fudge_gslcblas() -{ - STATUS("%p\n", cblas_sgemm); -} -#endif - - -UnitCell *rotate_cell(UnitCell *in, double omega, double phi, double rot) -{ - UnitCell *out; - double asx, asy, asz; - double bsx, bsy, bsz; - double csx, csy, csz; - double xnew, ynew, znew; - - cell_get_reciprocal(in, &asx, &asy, &asz, &bsx, &bsy, - &bsz, &csx, &csy, &csz); - - /* Rotate by "omega" about +z (parallel to c* and c unless triclinic) */ - xnew = asx*cos(omega) + asy*sin(omega); - ynew = -asx*sin(omega) + asy*cos(omega); - znew = asz; - asx = xnew; asy = ynew; asz = znew; - xnew = bsx*cos(omega) + bsy*sin(omega); - ynew = -bsx*sin(omega) + bsy*cos(omega); - znew = bsz; - bsx = xnew; bsy = ynew; bsz = znew; - xnew = csx*cos(omega) + csy*sin(omega); - ynew = -csx*sin(omega) + csy*cos(omega); - znew = csz; - csx = xnew; csy = ynew; csz = znew; - - /* Rotate by "phi" about +x (not parallel to anything specific) */ - xnew = asx; - ynew = asy*cos(phi) + asz*sin(phi); - znew = -asy*sin(phi) + asz*cos(phi); - asx = xnew; asy = ynew; asz = znew; - xnew = bsx; - ynew = bsy*cos(phi) + bsz*sin(phi); - znew = -bsy*sin(phi) + bsz*cos(phi); - bsx = xnew; bsy = ynew; bsz = znew; - xnew = csx; - ynew = csy*cos(phi) + csz*sin(phi); - znew = -csy*sin(phi) + csz*cos(phi); - csx = xnew; csy = ynew; csz = znew; - - /* Rotate by "rot" about the new +z (in-plane rotation) */ - xnew = asx*cos(rot) + asy*sin(rot); - ynew = -asx*sin(rot) + asy*cos(rot); - znew = asz; - asx = xnew; asy = ynew; asz = znew; - xnew = bsx*cos(rot) + bsy*sin(rot); - ynew = -bsx*sin(rot) + bsy*cos(rot); - znew = bsz; - bsx = xnew; bsy = ynew; bsz = znew; - xnew = csx*cos(rot) + csy*sin(rot); - ynew = -csx*sin(rot) + csy*cos(rot); - znew = csz; - csx = xnew; csy = ynew; csz = znew; - - out = cell_new_from_cell(in); - cell_set_reciprocal(out, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); - - return out; -} - - -int cell_is_sensible(UnitCell *cell) -{ - double a, b, c, al, be, ga; - - cell_get_parameters(cell, &a, &b, &c, &al, &be, &ga); - if ( al + be + ga >= 2.0*M_PI ) return 0; - if ( al + be - ga >= 2.0*M_PI ) return 0; - if ( al - be + ga >= 2.0*M_PI ) return 0; - if ( - al + be + ga >= 2.0*M_PI ) return 0; - if ( al + be + ga <= 0.0 ) return 0; - if ( al + be - ga <= 0.0 ) return 0; - if ( al - be + ga <= 0.0 ) return 0; - if ( - al + be + ga <= 0.0 ) return 0; - if ( isnan(al) ) return 0; - if ( isnan(be) ) return 0; - if ( isnan(ga) ) return 0; - return 1; -} diff --git a/src/cell.h b/src/cell.h deleted file mode 100644 index b5d31fc6..00000000 --- a/src/cell.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * cell.h - * - * Unit Cell Calculations - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifndef CELL_H -#define CELL_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "utils.h" - -/* A 3D vector in reciprocal space */ -struct rvec -{ - double u; - double v; - double w; -}; - - -/** - * UnitCell: - * - * This data structure is opaque. You must use the available accessor functions - * to read and write its contents. - **/ -typedef struct _unitcell UnitCell; - -extern UnitCell *cell_new(void); -extern UnitCell *cell_new_from_cell(UnitCell *orig); -extern void cell_free(UnitCell *cell); - -/* Lengths in m, angles in radians */ -extern UnitCell *cell_new_from_parameters(double a, double b, double c, - double alpha, double beta, double gamma); - -extern UnitCell *cell_new_from_reciprocal_axes(struct rvec as, struct rvec bs, - struct rvec cs); - -extern UnitCell *cell_new_from_direct_axes(struct rvec as, struct rvec bs, - struct rvec cs); - -extern void cell_set_cartesian(UnitCell *cell, - double ax, double ay, double az, - double bx, double by, double bz, - double cx, double cy, double cz); - -extern void cell_set_parameters(UnitCell *cell, double a, double b, double c, - double alpha, double beta, double gamma); - -extern void cell_set_cartesian_a(UnitCell *cell, double ax, double ay, double az); -extern void cell_set_cartesian_b(UnitCell *cell, double bx, double by, double bz); -extern void cell_set_cartesian_c(UnitCell *cell, double cx, double cy, double cz); -extern void cell_set_spacegroup(UnitCell *cell, const char *sym); -extern void cell_set_pointgroup(UnitCell *cell, const char *sym); - - -extern int cell_get_parameters(UnitCell *cell, double *a, double *b, double *c, - double *alpha, double *beta, double *gamma); - -extern int cell_get_cartesian(UnitCell *cell, - double *ax, double *ay, double *az, - double *bx, double *by, double *bz, - double *cx, double *cy, double *cz); - -extern int cell_get_reciprocal(UnitCell *cell, - double *asx, double *asy, double *asz, - double *bsx, double *bsy, double *bsz, - double *csx, double *csy, double *csz); - -extern void cell_set_reciprocal(UnitCell *cell, - double asx, double asy, double asz, - double bsx, double bsy, double bsz, - double csx, double csy, double csz); - -extern const char *cell_get_pointgroup(UnitCell *cell); - -extern const char *cell_get_spacegroup(UnitCell *cell); - -extern double resolution(UnitCell *cell, - signed int h, signed int k, signed int l); - -extern UnitCell *cell_rotate(UnitCell *in, struct quaternion quat); -extern UnitCell *rotate_cell(UnitCell *in, double omega, double phi, - double rot); - -extern void cell_print(UnitCell *cell); - -extern UnitCell *match_cell(UnitCell *cell, UnitCell *template, int verbose, - int reduce); - -extern UnitCell *match_cell_ab(UnitCell *cell, UnitCell *template); - -extern UnitCell *load_cell_from_pdb(const char *filename); - -extern int cell_is_sensible(UnitCell *cell); - -#endif /* CELL_H */ diff --git a/src/detector.c b/src/detector.c deleted file mode 100644 index 7f29ec82..00000000 --- a/src/detector.c +++ /dev/null @@ -1,1234 +0,0 @@ -/* - * detector.c - * - * Detector properties - * - * (c) 2006-2011 Thomas White <taw@physics.org> - * (c) 2011 Rick Kirian <rkirian@asu.edu> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#include <stdlib.h> -#include <math.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> -#include <ctype.h> - -#include "image.h" -#include "utils.h" -#include "diffraction.h" -#include "detector.h" -#include "beam-parameters.h" -#include "hdf5-file.h" - - -/** - * SECTION:detector - * @short_description: Detector geometry - * @title: Detector - * @section_id: - * @see_also: - * @include: "detector.h" - * @Image: - * - * This structure represents the detector geometry - */ - - -static int atob(const char *a) -{ - if ( strcasecmp(a, "true") == 0 ) return 1; - if ( strcasecmp(a, "false") == 0 ) return 0; - return atoi(a); -} - - -static int assplode_algebraic(const char *a_orig, char ***pbits) -{ - int len, i; - int nexp; - char **bits; - char *a; - int idx, istr; - - len = strlen(a_orig); - - /* Add plus at start if no sign there already */ - if ( (a_orig[0] != '+') && (a_orig[0] != '-') ) { - len += 1; - a = malloc(len+1); - snprintf(a, len+1, "+%s", a_orig); - a[len] = '\0'; - - } else { - a = strdup(a_orig); - } - - /* Count the expressions */ - nexp = 0; - for ( i=0; i<len; i++ ) { - if ( (a[i] == '+') || (a[i] == '-') ) nexp++; - } - - bits = calloc(nexp, sizeof(char *)); - - /* Break the string up */ - idx = -1; - istr = 0; - assert((a[0] == '+') || (a[0] == '-')); - for ( i=0; i<len; i++ ) { - - char ch; - - ch = a[i]; - - if ( (ch == '+') || (ch == '-') ) { - if ( idx >= 0 ) bits[idx][istr] = '\0'; - idx++; - bits[idx] = malloc(len+1); - istr = 0; - } - - if ( !isdigit(ch) && (ch != '.') && (ch != 'x') && (ch != 'y') - && (ch != '+') && (ch != '-') ) - { - ERROR("Invalid character '%C' found.\n", ch); - return 0; - } - - assert(idx >= 0); - bits[idx][istr++] = ch; - - } - if ( idx >= 0 ) bits[idx][istr] = '\0'; - - *pbits = bits; - free(a); - - return nexp; -} - - -/* Parses the scan directions (accounting for possible rotation) - * Assumes all white spaces have been already removed */ -static int dir_conv(const char *a, double *sx, double *sy) -{ - int n; - char **bits; - int i; - - *sx = 0.0; *sy = 0.0; - - n = assplode_algebraic(a, &bits); - - if ( n == 0 ) { - ERROR("Invalid direction '%s'\n", a); - return 1; - } - - for ( i=0; i<n; i++ ) { - - int len; - double val; - char axis; - int j; - - len = strlen(bits[i]); - assert(len != 0); - axis = bits[i][len-1]; - if ( (axis != 'x') && (axis != 'y') ) { - ERROR("Invalid symbol '%C' - must be x or y.\n", axis); - return 1; - } - - /* Chop off the symbol now it's dealt with */ - bits[i][len-1] = '\0'; - - /* Check for anything that isn't part of a number */ - for ( j=0; j<strlen(bits[i]); j++ ) { - if ( isdigit(bits[i][j]) ) continue; - if ( bits[i][j] == '+' ) continue; - if ( bits[i][j] == '-' ) continue; - if ( bits[i][j] == '.' ) continue; - ERROR("Invalid coefficient '%s'\n", bits[i]); - } - - if ( strlen(bits[i]) == 0 ) { - val = 1.0; - } else { - val = atof(bits[i]); - } - if ( strlen(bits[i]) == 1 ) { - if ( bits[i][0] == '+' ) val = 1.0; - if ( bits[i][0] == '-' ) val = -1.0; - } - if ( axis == 'x' ) { - *sx += val; - } else if ( axis == 'y' ) { - *sy += val; - } - - free(bits[i]); - - } - free(bits); - - //STATUS("'%s' -> %5.2fx + %5.2fy\n", a, *sx, *sy); - - return 0; -} - - -struct rvec get_q_for_panel(struct panel *p, double fs, double ss, - double *ttp, double k) -{ - struct rvec q; - double twotheta, r, az; - double rx, ry; - double xs, ys; - - /* Convert xs and ys, which are in fast scan/slow scan coordinates, - * to x and y */ - xs = fs*p->fsx + ss*p->ssx; - ys = fs*p->fsy + ss*p->ssy; - - rx = (xs + p->cnx) / p->res; - ry = (ys + p->cny) / p->res; - - /* Calculate q-vector for this sub-pixel */ - r = sqrt(pow(rx, 2.0) + pow(ry, 2.0)); - - twotheta = atan2(r, p->clen); - az = atan2(ry, rx); - if ( ttp != NULL ) *ttp = twotheta; - - q.u = k * sin(twotheta)*cos(az); - q.v = k * sin(twotheta)*sin(az); - q.w = k * (cos(twotheta) - 1.0); - - return q; -} - - -struct rvec get_q(struct image *image, double fs, double ss, - double *ttp, double k) -{ - struct panel *p; - const unsigned int fsi = fs; - const unsigned int ssi = ss; /* Explicit rounding */ - - /* Determine which panel to use */ - p = find_panel(image->det, fsi, ssi); - assert(p != NULL); - - return get_q_for_panel(p, fs-(double)p->min_fs, ss-(double)p->min_ss, - ttp, k); -} - - -int in_bad_region(struct detector *det, double fs, double ss) -{ - double rx, ry; - struct panel *p; - double xs, ys; - int i; - - /* Determine which panel to use */ - p = find_panel(det, fs, ss); - - /* No panel found -> definitely bad! */ - if ( p == NULL ) return 1; - - /* Convert xs and ys, which are in fast scan/slow scan coordinates, - * to x and y */ - xs = (fs-(double)p->min_fs)*p->fsx + (ss-(double)p->min_ss)*p->ssx; - ys = (fs-(double)p->min_fs)*p->fsy + (ss-(double)p->min_ss)*p->ssy; - - rx = xs + p->cnx; - ry = ys + p->cny; - - for ( i=0; i<det->n_bad; i++ ) { - struct badregion *b = &det->bad[i]; - if ( rx < b->min_x ) continue; - if ( rx > b->max_x ) continue; - if ( ry < b->min_y ) continue; - if ( ry > b->max_y ) continue; - return 1; - } - - return 0; -} - - -double get_tt(struct image *image, double fs, double ss) -{ - double r, rx, ry; - struct panel *p; - double xs, ys; - - p = find_panel(image->det, fs, ss); - - /* Convert xs and ys, which are in fast scan/slow scan coordinates, - * to x and y */ - xs = (fs-p->min_fs)*p->fsx + (ss-p->min_ss)*p->ssx; - ys = (fs-p->min_fs)*p->fsy + (ss-p->min_ss)*p->ssy; - - rx = (xs + p->cnx) / p->res; - ry = (ys + p->cny) / p->res; - - r = sqrt(pow(rx, 2.0) + pow(ry, 2.0)); - - return atan2(r, p->clen); -} - - -void record_image(struct image *image, int do_poisson) -{ - int x, y; - double total_energy, energy_density; - double ph_per_e; - double area; - double max_tt = 0.0; - int n_inf1 = 0; - int n_neg1 = 0; - int n_nan1 = 0; - int n_inf2 = 0; - int n_neg2 = 0; - int n_nan2 = 0; - - /* How many photons are scattered per electron? */ - area = M_PI*pow(image->beam->beam_radius, 2.0); - total_energy = image->beam->fluence * ph_lambda_to_en(image->lambda); - energy_density = total_energy / area; - ph_per_e = (image->beam->fluence /area) * pow(THOMSON_LENGTH, 2.0); - STATUS("Fluence = %8.2e photons, " - "Energy density = %5.3f kJ/cm^2, " - "Total energy = %5.3f microJ\n", - image->beam->fluence, energy_density/1e7, total_energy*1e6); - - for ( x=0; x<image->width; x++ ) { - for ( y=0; y<image->height; y++ ) { - - double counts; - double cf; - double intensity, sa; - double pix_area, Lsq; - double xs, ys, rx, ry; - double dsq, proj_area; - struct panel *p; - - intensity = (double)image->data[x + image->width*y]; - if ( isinf(intensity) ) n_inf1++; - if ( intensity < 0.0 ) n_neg1++; - if ( isnan(intensity) ) n_nan1++; - - p = find_panel(image->det, x, y); - - /* Area of one pixel */ - pix_area = pow(1.0/p->res, 2.0); - Lsq = pow(p->clen, 2.0); - - /* Area of pixel as seen from crystal (approximate) */ - proj_area = pix_area * cos(image->twotheta[x + image->width*y]); - - /* Calculate distance from crystal to pixel */ - xs = (x-p->min_fs)*p->fsx + (y-p->min_ss)*p->ssx; - ys = (x-p->min_fs)*p->fsy + (y-p->min_ss)*p->ssy; - rx = (xs + p->cnx) / p->res; - ry = (ys + p->cny) / p->res; - dsq = sqrt(pow(rx, 2.0) + pow(ry, 2.0)); - - /* Projected area of pixel divided by distance squared */ - sa = proj_area / (dsq + Lsq); - - if ( do_poisson ) { - counts = poisson_noise(intensity * ph_per_e - * sa * image->beam->dqe ); - } else { - cf = intensity * ph_per_e * sa * image->beam->dqe; - counts = cf; - } - - image->data[x + image->width*y] = counts - * image->beam->adu_per_photon; - - /* Sanity checks */ - if ( isinf(image->data[x+image->width*y]) ) n_inf2++; - if ( isnan(image->data[x+image->width*y]) ) n_nan2++; - if ( image->data[x+image->width*y] < 0.0 ) n_neg2++; - - if ( image->twotheta[x + image->width*y] > max_tt ) { - max_tt = image->twotheta[x + image->width*y]; - } - - } - progress_bar(x, image->width-1, "Post-processing"); - } - - STATUS("Max 2theta = %.2f deg, min d = %.2f nm\n", - rad2deg(max_tt), (image->lambda/(2.0*sin(max_tt/2.0)))/1e-9); - - double tt_side = image->twotheta[(image->width/2)+image->width*0]; - STATUS("At middle of bottom edge: %.2f deg, min d = %.2f nm\n", - rad2deg(tt_side), (image->lambda/(2.0*sin(tt_side/2.0)))/1e-9); - - tt_side = image->twotheta[0+image->width*(image->height/2)]; - STATUS("At middle of left edge: %.2f deg, min d = %.2f nm\n", - rad2deg(tt_side), (image->lambda/(2.0*sin(tt_side/2.0)))/1e-9); - - STATUS("Halve the d values to get the voxel size for a synthesis.\n"); - - if ( n_neg1 + n_inf1 + n_nan1 + n_neg2 + n_inf2 + n_nan2 ) { - ERROR("WARNING: The raw calculation produced %i negative" - " values, %i infinities and %i NaNs.\n", - n_neg1, n_inf1, n_nan1); - ERROR("WARNING: After processing, there were %i negative" - " values, %i infinities and %i NaNs.\n", - n_neg2, n_inf2, n_nan2); - } -} - - -struct panel *find_panel(struct detector *det, double fs, double ss) -{ - int p; - - for ( p=0; p<det->n_panels; p++ ) { - if ( (fs >= det->panels[p].min_fs) - && (fs <= det->panels[p].max_fs) - && (ss >= det->panels[p].min_ss) - && (ss <= det->panels[p].max_ss) ) { - return &det->panels[p]; - } - } - - return NULL; -} - - -int find_panel_number(struct detector *det, int fs, int ss) -{ - int p; - - for ( p=0; p<det->n_panels; p++ ) { - if ( (fs >= det->panels[p].min_fs) - && (fs <= det->panels[p].max_fs) - && (ss >= det->panels[p].min_ss) - && (ss <= det->panels[p].max_ss) ) return p; - } - - return -1; -} - - -void fill_in_values(struct detector *det, struct hdfile *f) -{ - int i; - - for ( i=0; i<det->n_panels; i++ ) { - - struct panel *p = &det->panels[i]; - - if ( p->clen_from != NULL ) { - p->clen = get_value(f, p->clen_from) * 1.0e-3; - free(p->clen_from); - p->clen_from = NULL; - } - - p->clen += p->coffset; - - } -} - - -static struct panel *new_panel(struct detector *det, const char *name) -{ - struct panel *new; - - det->n_panels++; - det->panels = realloc(det->panels, det->n_panels*sizeof(struct panel)); - - new = &det->panels[det->n_panels-1]; - memcpy(new, &det->defaults, sizeof(struct panel)); - - /* Create a new copy of the camera length location if needed */ - if ( new->clen_from != NULL ) { - new->clen_from = strdup(new->clen_from); - } - strcpy(new->name, name); - - return new; -} - - -static struct badregion *new_bad_region(struct detector *det, const char *name) -{ - struct badregion *new; - - det->n_bad++; - det->bad = realloc(det->bad, det->n_bad*sizeof(struct badregion)); - - new = &det->bad[det->n_bad-1]; - new->min_x = NAN; - new->max_x = NAN; - new->min_y = NAN; - new->max_y = NAN; - strcpy(new->name, name); - - return new; -} - - -struct panel *find_panel_by_name(struct detector *det, const char *name) -{ - int i; - - for ( i=0; i<det->n_panels; i++ ) { - if ( strcmp(det->panels[i].name, name) == 0 ) { - return &det->panels[i]; - } - } - - return NULL; -} - - -static struct badregion *find_bad_region_by_name(struct detector *det, - const char *name) -{ - int i; - - for ( i=0; i<det->n_bad; i++ ) { - if ( strcmp(det->bad[i].name, name) == 0 ) { - return &det->bad[i]; - } - } - - return NULL; -} - - -static char *find_or_add_rg(struct detector *det, const char *name) -{ - int i; - char **new; - char *tmp; - - for ( i=0; i<det->num_rigid_groups; i++ ) { - - if ( strcmp(det->rigid_groups[i], name) == 0 ) { - return det->rigid_groups[i]; - } - - } - - new = realloc(det->rigid_groups, - (1+det->num_rigid_groups)*sizeof(char *)); - if ( new == NULL ) return NULL; - - det->rigid_groups = new; - - tmp = strdup(name); - det->rigid_groups[det->num_rigid_groups] = tmp; - - det->num_rigid_groups++; - - return tmp; -} - - -static int parse_field_for_panel(struct panel *panel, const char *key, - const char *val, struct detector *det) -{ - int reject = 0; - - if ( strcmp(key, "min_fs") == 0 ) { - panel->min_fs = atof(val); - } else if ( strcmp(key, "max_fs") == 0 ) { - panel->max_fs = atof(val); - } else if ( strcmp(key, "min_ss") == 0 ) { - panel->min_ss = atof(val); - } else if ( strcmp(key, "max_ss") == 0 ) { - panel->max_ss = atof(val); - } else if ( strcmp(key, "corner_x") == 0 ) { - panel->cnx = atof(val); - } else if ( strcmp(key, "corner_y") == 0 ) { - panel->cny = atof(val); - } else if ( strcmp(key, "rigid_group") == 0 ) { - panel->rigid_group = find_or_add_rg(det, val); - } else if ( strcmp(key, "clen") == 0 ) { - - char *end; - double v = strtod(val, &end); - if ( end == val ) { - /* This means "fill in later" */ - panel->clen = -1.0; - panel->clen_from = strdup(val); - } else { - panel->clen = v; - panel->clen_from = NULL; - } - - } else if ( strcmp(key, "coffset") == 0) { - panel->coffset = atof(val); - } else if ( strcmp(key, "res") == 0 ) { - panel->res = atof(val); - } else if ( strcmp(key, "peak_sep") == 0 ) { - panel->peak_sep = atof(val); - } else if ( strcmp(key, "integr_radius") == 0 ) { - panel->integr_radius = atof(val); - } else if ( strcmp(key, "badrow_direction") == 0 ) { - panel->badrow = val[0]; /* First character only */ - if ( (panel->badrow != 'x') && (panel->badrow != 'y') - && (panel->badrow != 'f') && (panel->badrow != 's') - && (panel->badrow != '-') ) { - ERROR("badrow_direction must be x, y, f, s or '-'\n"); - ERROR("Assuming '-'\n."); - panel->badrow = '-'; - } - if ( panel->badrow == 'x' ) panel->badrow = 'f'; - if ( panel->badrow == 'y' ) panel->badrow = 's'; - } else if ( strcmp(key, "no_index") == 0 ) { - panel->no_index = atob(val); - } else if ( strcmp(key, "fs") == 0 ) { - if ( dir_conv(val, &panel->fsx, &panel->fsy) != 0 ) { - ERROR("Invalid fast scan direction '%s'\n", val); - reject = 1; - } - } else if ( strcmp(key, "ss") == 0 ) { - if ( dir_conv(val, &panel->ssx, &panel->ssy) != 0 ) { - ERROR("Invalid slow scan direction '%s'\n", val); - reject = 1; - } - } else { - ERROR("Unrecognised field '%s'\n", key); - } - - return reject; -} - - -static int parse_field_bad(struct badregion *panel, const char *key, - const char *val) -{ - int reject = 0; - - if ( strcmp(key, "min_x") == 0 ) { - panel->min_x = atof(val); - } else if ( strcmp(key, "max_x") == 0 ) { - panel->max_x = atof(val); - } else if ( strcmp(key, "min_y") == 0 ) { - panel->min_y = atof(val); - } else if ( strcmp(key, "max_y") == 0 ) { - panel->max_y = atof(val); - } else { - ERROR("Unrecognised field '%s'\n", key); - } - - return reject; -} - - -static void parse_toplevel(struct detector *det, const char *key, - const char *val) -{ - if ( strcmp(key, "mask") == 0 ) { - - det->mask = strdup(val); - - } else if ( strcmp(key, "mask_bad") == 0 ) { - - char *end; - double v = strtod(val, &end); - - if ( end != val ) { - det->mask_bad = v; - } - - } else if ( strcmp(key, "mask_good") == 0 ) { - - char *end; - double v = strtod(val, &end); - - if ( end != val ) { - det->mask_good = v; - } - - } else if ( strcmp(key, "peak_sep") == 0 ) { - det->defaults.peak_sep = atof(val); - } else if ( strcmp(key, "integr_radius") == 0 ) { - det->defaults.integr_radius = atof(val); - } else if ( parse_field_for_panel(&det->defaults, key, val, det) ) { - ERROR("Unrecognised top level field '%s'\n", key); - } -} - - -struct detector *get_detector_geometry(const char *filename) -{ - FILE *fh; - struct detector *det; - char *rval; - char **bits; - int i; - int reject = 0; - int x, y, max_fs, max_ss; - - fh = fopen(filename, "r"); - if ( fh == NULL ) return NULL; - - det = calloc(1, sizeof(struct detector)); - if ( det == NULL ) { - fclose(fh); - return NULL; - } - - det->n_panels = 0; - det->panels = NULL; - det->n_bad = 0; - det->bad = NULL; - det->mask_good = 0; - det->mask_bad = 0; - det->mask = NULL; - det->num_rigid_groups = 0; - det->rigid_groups = NULL; - - /* The default defaults... */ - det->defaults.min_fs = -1; - det->defaults.min_ss = -1; - det->defaults.max_fs = -1; - det->defaults.max_ss = -1; - det->defaults.cnx = NAN; - det->defaults.cny = NAN; - det->defaults.clen = -1.0; - det->defaults.coffset = 0.0; - det->defaults.res = -1.0; - det->defaults.badrow = '-'; - det->defaults.no_index = 0; - det->defaults.peak_sep = 50.0; - det->defaults.integr_radius = 3.0; - det->defaults.fsx = 1.0; - det->defaults.fsy = 0.0; - det->defaults.ssx = 0.0; - det->defaults.ssy = 1.0; - det->defaults.rigid_group = NULL; - strncpy(det->defaults.name, "", 1023); - - do { - - int n1, n2; - char **path; - char line[1024]; - struct badregion *badregion = NULL; - struct panel *panel = NULL; - char *key; - char wholeval[1024]; - - rval = fgets(line, 1023, fh); - if ( rval == NULL ) break; - chomp(line); - - if ( line[0] == ';' ) continue; - - n1 = assplode(line, " \t", &bits, ASSPLODE_NONE); - if ( n1 < 3 ) { - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - continue; - } - - /* Stitch the pieces of the "value" back together */ - wholeval[0] = '\0'; /* Empty string */ - for ( i=2; i<n1; i++ ) { - if ( bits[i][0] == ';' ) break; /* Stop on comment */ - strncat(wholeval, bits[i], 1023); - } - - if ( bits[1][0] != '=' ) { - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - continue; - } - - n2 = assplode(bits[0], "/\\.", &path, ASSPLODE_NONE); - if ( n2 < 2 ) { - /* This was a top-level option, not handled above. */ - parse_toplevel(det, bits[0], bits[2]); - for ( i=0; i<n1; i++ ) free(bits[i]); - free(bits); - for ( i=0; i<n2; i++ ) free(path[i]); - free(path); - continue; - } - - if ( strncmp(path[0], "bad", 3) == 0 ) { - badregion = find_bad_region_by_name(det, path[0]); - if ( badregion == NULL ) { - badregion = new_bad_region(det, path[0]); - } - } else { - panel = find_panel_by_name(det, path[0]); - if ( panel == NULL ) { - panel = new_panel(det, path[0]); - } - } - - key = path[1]; - - if ( panel != NULL ) { - if ( parse_field_for_panel(panel, path[1], - wholeval, det) ) - { - reject = 1; - } - } else { - if ( parse_field_bad(badregion, path[1], wholeval) ) { - reject = 1; - } - } - - for ( i=0; i<n1; i++ ) free(bits[i]); - for ( i=0; i<n2; i++ ) free(path[i]); - free(bits); - free(path); - - } while ( rval != NULL ); - - if ( det->n_panels == -1 ) { - ERROR("No panel descriptions in geometry file.\n"); - fclose(fh); - free(det); - return NULL; - } - - max_fs = 0; - max_ss = 0; - for ( i=0; i<det->n_panels; i++ ) { - - if ( det->panels[i].min_fs < 0 ) { - ERROR("Please specify the minimum FS coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( det->panels[i].max_fs < 0 ) { - ERROR("Please specify the maximum FS coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( det->panels[i].min_ss < 0 ) { - ERROR("Please specify the minimum SS coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( det->panels[i].max_ss < 0 ) { - ERROR("Please specify the maximum SS coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( isnan(det->panels[i].cnx) ) { - ERROR("Please specify the corner X coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( isnan(det->panels[i].cny) ) { - ERROR("Please specify the corner Y coordinate for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( (det->panels[i].clen < 0.0) - && (det->panels[i].clen_from == NULL) ) { - ERROR("Please specify the camera length for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - if ( det->panels[i].res < 0 ) { - ERROR("Please specify the resolution for" - " panel %s\n", det->panels[i].name); - reject = 1; - } - /* It's OK if the badrow direction is '0' */ - /* It's not a problem if "no_index" is still zero */ - /* The default peak_sep is OK (maybe) */ - /* The default transformation matrix is at least valid */ - - if ( det->panels[i].max_fs > max_fs ) { - max_fs = det->panels[i].max_fs; - } - if ( det->panels[i].max_ss > max_ss ) { - max_ss = det->panels[i].max_ss; - } - - } - - for ( i=0; i<det->n_bad; i++ ) { - - if ( isnan(det->bad[i].min_x) ) { - ERROR("Please specify the minimum x coordinate for" - " bad region %s\n", det->bad[i].name); - reject = 1; - } - if ( isnan(det->bad[i].min_y) ) { - ERROR("Please specify the minimum y coordinate for" - " bad region %s\n", det->bad[i].name); - reject = 1; - } - if ( isnan(det->bad[i].max_x) ) { - ERROR("Please specify the maximum x coordinate for" - " bad region %s\n", det->bad[i].name); - reject = 1; - } - if ( isnan(det->bad[i].max_y) ) { - ERROR("Please specify the maximum y coordinate for" - " bad region %s\n", det->bad[i].name); - reject = 1; - } - } - - for ( x=0; x<=max_fs; x++ ) { - for ( y=0; y<=max_ss; y++ ) { - if ( find_panel(det, x, y) == NULL ) { - ERROR("Detector geometry invalid: contains gaps.\n"); - reject = 1; - goto out; - } - } - } - -out: - det->max_fs = max_fs; - det->max_ss = max_ss; - - /* Calculate matrix inverse */ - for ( i=0; i<det->n_panels; i++ ) { - - struct panel *p; - double d; - - p = &det->panels[i]; - - if ( p->fsx*p->ssy == p->ssx*p->fsy ) { - ERROR("Panel %i transformation singular.\n", i); - reject = 1; - } - - d = (double)p->fsx*p->ssy - p->ssx*p->fsy; - p->xfs = p->ssy / d; - p->yfs = -p->ssx / d; - p->xss = -p->fsy / d; - p->yss = p->fsx / d; - - } - - if ( reject ) return NULL; - - fclose(fh); - - return det; -} - - -void free_detector_geometry(struct detector *det) -{ - int i; - - for ( i=0; i<det->num_rigid_groups; i++ ) { - free(det->rigid_groups[i]); - } - free(det->rigid_groups); - - free(det->panels); - free(det->bad); - free(det->mask); - free(det); -} - - -struct detector *copy_geom(const struct detector *in) -{ - struct detector *out; - int i; - - out = malloc(sizeof(struct detector)); - memcpy(out, in, sizeof(struct detector)); - - if ( in->mask != NULL ) { - out->mask = strdup(in->mask); - } else { - out->mask = NULL; /* = in->mask */ - } - - out->panels = malloc(out->n_panels * sizeof(struct panel)); - memcpy(out->panels, in->panels, out->n_panels * sizeof(struct panel)); - - out->bad = malloc(out->n_bad * sizeof(struct badregion)); - memcpy(out->bad, in->bad, out->n_bad * sizeof(struct badregion)); - - if ( in->rigid_groups != NULL ) { - - out->rigid_groups = malloc(out->num_rigid_groups*sizeof(char *)); - memcpy(out->rigid_groups, in->rigid_groups, - out->num_rigid_groups*sizeof(char *)); - - for ( i=0; i<in->num_rigid_groups; i++ ) { - out->rigid_groups[i] = strdup(in->rigid_groups[i]); - } - - } - - for ( i=0; i<out->n_panels; i++ ) { - - struct panel *p; - - p = &out->panels[i]; - - if ( p->clen_from != NULL ) { - /* Make a copy of the clen_from fields unique to this - * copy of the structure. */ - p->clen_from = strdup(p->clen_from); - } - - } - - for ( i=0; i<in->num_rigid_groups; i++ ) { - - int j; - char *rg = in->rigid_groups[i]; - char *rgn = out->rigid_groups[i]; - - for ( j=0; j<in->n_panels; j++ ) { - - if ( in->panels[j].rigid_group == rg ) { - out->panels[j].rigid_group = rgn; - } - - } - - } - - return out; -} - - -struct detector *simple_geometry(const struct image *image) -{ - struct detector *geom; - - geom = calloc(1, sizeof(struct detector)); - - geom->n_panels = 1; - geom->panels = calloc(1, sizeof(struct panel)); - - geom->panels[0].min_fs = 0; - geom->panels[0].max_fs = image->width-1; - geom->panels[0].min_ss = 0; - geom->panels[0].max_ss = image->height-1; - geom->panels[0].cnx = -image->width / 2.0; - geom->panels[0].cny = -image->height / 2.0; - geom->panels[0].rigid_group = NULL; - - geom->panels[0].fsx = 1; - geom->panels[0].fsy = 0; - geom->panels[0].ssx = 0; - geom->panels[0].ssy = 1; - - geom->panels[0].xfs = 1; - geom->panels[0].xss = 0; - geom->panels[0].yfs = 0; - geom->panels[0].yss = 1; - - return geom; -} - - -int reverse_2d_mapping(double x, double y, double *pfs, double *pss, - struct detector *det) -{ - int i; - - for ( i=0; i<det->n_panels; i++ ) { - - struct panel *p = &det->panels[i]; - double cx, cy, fs, ss; - - /* Get position relative to corner */ - cx = x - p->cnx; - cy = y - p->cny; - - /* Reverse the transformation matrix */ - fs = cx*p->xfs + cy*p->yfs; - ss = cx*p->xss + cy*p->yss; - - /* In range? */ - if ( fs < 0 ) continue; - if ( ss < 0 ) continue; - if ( fs > (p->max_fs-p->min_fs+1) ) continue; - if ( ss > (p->max_ss-p->min_ss+1) ) continue; - - *pfs = fs + p->min_fs; - *pss = ss + p->min_ss; - return 0; - - } - - return 1; -} - - -static void check_extents(struct panel p, double *min_x, double *min_y, - double *max_x, double *max_y, double fs, double ss) -{ - double xs, ys, rx, ry; - - xs = fs*p.fsx + ss*p.ssx; - ys = fs*p.fsy + ss*p.ssy; - - rx = xs + p.cnx; - ry = ys + p.cny; - - if ( rx > *max_x ) *max_x = rx; - if ( ry > *max_y ) *max_y = ry; - if ( rx < *min_x ) *min_x = rx; - if ( ry < *min_y ) *min_y = ry; -} - - -double largest_q(struct image *image) -{ - int fs, ss; - double ttm = 0.0; - double qmax = 0.0; - - for ( fs=0; fs<image->width; fs++ ) { - for ( ss=0; ss<image->height; ss++ ) { - - struct rvec q; - double tt; - - q = get_q(image, fs, ss, &tt, 1.0/image->lambda); - - if ( tt > ttm ) { - qmax = modulus(q.u, q.v, q.w); - ttm = tt; - } - - } - } - - return qmax; -} - - -double smallest_q(struct image *image) -{ - int fs, ss; - double ttm = +INFINITY; - double qmin = +INFINITY; - for ( fs=0; fs<image->width; fs++ ) { - for ( ss=0; ss<image->height; ss++ ) { - - struct rvec q; - double tt; - - q = get_q(image, fs, ss, &tt, 1.0/image->lambda); - - if ( tt < ttm ) { - qmin = modulus(q.u, q.v, q.w); - ttm = tt; - } - - } - } - - return qmin; -} - - -void get_pixel_extents(struct detector *det, - double *min_x, double *min_y, - double *max_x, double *max_y) -{ - int i; - - *min_x = 0.0; - *max_x = 0.0; - *min_y = 0.0; - *max_y = 0.0; - - /* To determine the maximum extents of the detector, put all four - * corners of each panel through the transformations and watch for the - * biggest */ - - for ( i=0; i<det->n_panels; i++ ) { - - check_extents(det->panels[i], min_x, min_y, max_x, max_y, - 0.0, - 0.0); - - check_extents(det->panels[i], min_x, min_y, max_x, max_y, - 0.0, - det->panels[i].max_ss-det->panels[i].min_ss+1); - - check_extents(det->panels[i], min_x, min_y, max_x, max_y, - det->panels[i].max_fs-det->panels[i].min_fs+1, - 0.0); - - check_extents(det->panels[i], min_x, min_y, max_x, max_y, - det->panels[i].max_fs-det->panels[i].min_fs+1, - det->panels[i].max_ss-det->panels[i].min_ss+1); - - - } -} - - -int write_detector_geometry(const char *filename, struct detector *det) -{ - struct panel *p; - int pi; - FILE *fh; - - if ( filename == NULL ) return 2; - if ( det->n_panels < 1 ) return 3; - - fh = fopen(filename, "w"); - if ( fh == NULL ) return 1; - - for ( pi=0; pi<det->n_panels; pi++) { - - p = &(det->panels[pi]); - - if ( p == NULL ) return 4; - - if ( pi > 0 ) fprintf(fh, "\n"); - - fprintf(fh, "%s/min_fs = %d\n", p->name, p->min_fs); - fprintf(fh, "%s/min_ss = %d\n", p->name, p->min_ss); - fprintf(fh, "%s/max_fs = %d\n", p->name, p->max_fs); - fprintf(fh, "%s/max_ss = %d\n", p->name, p->max_ss); - fprintf(fh, "%s/badrow_direction = %C\n", p->name, p->badrow); - fprintf(fh, "%s/res = %g\n", p->name, p->res); - fprintf(fh, "%s/peak_sep = %g\n", p->name, p->peak_sep); - fprintf(fh, "%s/clen = %s\n", p->name, p->clen_from); - fprintf(fh, "%s/fs = %+fx %+fy\n", p->name, p->fsx, p->fsy); - fprintf(fh, "%s/ss = %+fx %+fy\n", p->name, p->ssx, p->ssy); - fprintf(fh, "%s/corner_x = %g\n", p->name, p->cnx); - fprintf(fh, "%s/corner_y = %g\n", p->name, p->cny); - - if ( p->no_index ) { - fprintf(fh, "%s/no_index = 1\n", p->name); - } /* else don't clutter up the file */ - - if ( p->rigid_group != NULL ) { - fprintf(fh, "%s/rigid_group = %s\n", - p->name, p->rigid_group); - } - - } - fclose(fh); - - return 0; -} diff --git a/src/detector.h b/src/detector.h deleted file mode 100644 index dd5dccec..00000000 --- a/src/detector.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * detector.h - * - * Detector properties - * - * (c) 2006-2011 Thomas White <taw@physics.org> - * (c) 2011 Rick Kirian <rkirian@asu.edu> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef DETECTOR_H -#define DETECTOR_H - -struct image; -struct hdfile; - -#include "hdf5-file.h" -#include "image.h" - - -struct panel -{ - char name[1024]; /* Name for this panel */ - - int min_fs; /* Smallest FS value considered to be in the panel */ - int max_fs; /* Largest FS value considered to be in this panel */ - int min_ss; /* ... and so on */ - int max_ss; - double cnx; /* Location of corner (min_fs,min_ss) in pixels */ - double cny; - double coffset; - double clen; /* Camera length in metres */ - char *clen_from; - double res; /* Resolution in pixels per metre */ - char badrow; /* 'x' or 'y' */ - int no_index; /* Don't index peaks in this panel if non-zero */ - double peak_sep; /* Characteristic peak separation */ - double integr_radius; /* Peak integration radius */ - char *rigid_group; /* Rigid group, or -1 for none */ - - double fsx; - double fsy; - double ssx; - double ssy; - - double xfs; - double yfs; - double xss; - double yss; -}; - - -struct badregion -{ - char name[1024]; - double min_x; - double max_x; - double min_y; - double max_y; -}; - - -struct detector -{ - struct panel *panels; - int n_panels; - - int max_fs; - int max_ss; /* Size of overall array needed, minus 1 */ - - struct badregion *bad; - int n_bad; - - char *mask; - unsigned int mask_bad; - unsigned int mask_good; - - char **rigid_groups; - int num_rigid_groups; - - struct panel defaults; -}; - - -extern struct rvec get_q(struct image *image, double fs, double ss, - double *ttp, double k); - -extern struct rvec get_q_for_panel(struct panel *p, double fs, double ss, - double *ttp, double k); - -extern double get_tt(struct image *image, double xs, double ys); - -extern int in_bad_region(struct detector *det, double fs, double ss); - -extern void record_image(struct image *image, int do_poisson); - -extern struct panel *find_panel(struct detector *det, double fs, double ss); - -extern int find_panel_number(struct detector *det, int fs, int ss); - -extern struct detector *get_detector_geometry(const char *filename); - -extern void free_detector_geometry(struct detector *det); - -extern struct detector *simple_geometry(const struct image *image); - -extern void get_pixel_extents(struct detector *det, - double *min_x, double *min_y, - double *max_x, double *max_y); - -extern void fill_in_values(struct detector *det, struct hdfile *f); - -extern struct detector *copy_geom(const struct detector *in); - -extern int reverse_2d_mapping(double x, double y, double *pfs, double *pss, - struct detector *det); - -extern double largest_q(struct image *image); - -extern double smallest_q(struct image *image); - -extern struct panel *find_panel_by_name(struct detector *det, const char *name); - - -#endif /* DETECTOR_H */ diff --git a/src/hdf5-file.c b/src/hdf5-file.c deleted file mode 100644 index 355e97f1..00000000 --- a/src/hdf5-file.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * hdf5-file.c - * - * Read/write HDF5 data files - * - * (c) 2006-2011 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <stdint.h> -#include <hdf5.h> -#include <assert.h> - -#include "image.h" -#include "hdf5-file.h" -#include "utils.h" - - -struct hdfile { - - const char *path; /* Current data path */ - - size_t nx; /* Image width */ - size_t ny; /* Image height */ - - hid_t fh; /* HDF file handle */ - hid_t dh; /* Dataset handle */ - - int data_open; /* True if dh is initialised */ -}; - - -struct hdfile *hdfile_open(const char *filename) -{ - struct hdfile *f; - - f = malloc(sizeof(struct hdfile)); - if ( f == NULL ) return NULL; - - /* Please stop spamming my terminal */ - H5Eset_auto2(H5E_DEFAULT, NULL, NULL); - - f->fh = H5Fopen(filename, H5F_ACC_RDONLY, H5P_DEFAULT); - if ( f->fh < 0 ) { - ERROR("Couldn't open file: %s\n", filename); - free(f); - return NULL; - } - - f->data_open = 0; - - return f; -} - - -int hdfile_set_image(struct hdfile *f, const char *path) -{ - hsize_t size[2]; - hsize_t max_size[2]; - hid_t sh; - - f->dh = H5Dopen2(f->fh, path, H5P_DEFAULT); - if ( f->dh < 0 ) { - ERROR("Couldn't open dataset\n"); - return -1; - } - f->data_open = 1; - - sh = H5Dget_space(f->dh); - if ( H5Sget_simple_extent_ndims(sh) != 2 ) { - ERROR("Dataset is not two-dimensional\n"); - return -1; - } - H5Sget_simple_extent_dims(sh, size, max_size); - H5Sclose(sh); - - f->nx = size[0]; - f->ny = size[1]; - - return 0; -} - - -int get_peaks(struct image *image, struct hdfile *f, const char *p) -{ - hid_t dh, sh; - hsize_t size[2]; - hsize_t max_size[2]; - int i; - float *buf; - herr_t r; - int tw; - - dh = H5Dopen2(f->fh, p, H5P_DEFAULT); - if ( dh < 0 ) { - ERROR("Peak list (%s) not found.\n", p); - return 1; - } - - sh = H5Dget_space(dh); - if ( sh < 0 ) { - H5Dclose(dh); - ERROR("Couldn't get dataspace for peak list.\n"); - return 1; - } - - if ( H5Sget_simple_extent_ndims(sh) != 2 ) { - ERROR("Peak list has the wrong dimensionality (%i).\n", - H5Sget_simple_extent_ndims(sh)); - H5Sclose(sh); - H5Dclose(dh); - return 1; - } - - H5Sget_simple_extent_dims(sh, size, max_size); - - tw = size[1]; - if ( (tw != 3) && (tw != 4) ) { - H5Sclose(sh); - H5Dclose(dh); - ERROR("Peak list has the wrong dimensions.\n"); - return 1; - } - - buf = malloc(sizeof(float)*size[0]*size[1]); - if ( buf == NULL ) { - H5Sclose(sh); - H5Dclose(dh); - ERROR("Couldn't reserve memory for the peak list.\n"); - return 1; - } - r = H5Dread(dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); - if ( r < 0 ) { - ERROR("Couldn't read peak list.\n"); - free(buf); - return 1; - } - - if ( image->features != NULL ) { - image_feature_list_free(image->features); - } - image->features = image_feature_list_new(); - - for ( i=0; i<size[0]; i++ ) { - - float fs, ss, val; - struct panel *p; - - fs = buf[tw*i+0]; - ss = buf[tw*i+1]; - val = buf[tw*i+2]; - - p = find_panel(image->det, fs, ss); - if ( p == NULL ) continue; - if ( p->no_index ) continue; - - image_add_feature(image->features, fs, ss, image, val, NULL); - - } - - free(buf); - H5Sclose(sh); - H5Dclose(dh); - - return 0; -} - - -static void cleanup(hid_t fh) -{ - int n_ids, i; - hid_t ids[256]; - - n_ids = H5Fget_obj_ids(fh, H5F_OBJ_ALL, 256, ids); - for ( i=0; i<n_ids; i++ ) { - - hid_t id; - H5I_type_t type; - - id = ids[i]; - type = H5Iget_type(id); - - if ( type == H5I_GROUP ) H5Gclose(id); - if ( type == H5I_DATASET ) H5Dclose(id); - if ( type == H5I_DATATYPE ) H5Tclose(id); - if ( type == H5I_DATASPACE ) H5Sclose(id); - if ( type == H5I_ATTR ) H5Aclose(id); - - } -} - - -void hdfile_close(struct hdfile *f) -{ - if ( f->data_open ) { - H5Dclose(f->dh); - } - cleanup(f->fh); - - H5Fclose(f->fh); - free(f); -} - - -int hdf5_write(const char *filename, const void *data, - int width, int height, int type) -{ - hid_t fh, gh, sh, dh; /* File, group, dataspace and data handles */ - hid_t ph; /* Property list */ - herr_t r; - hsize_t size[2]; - hsize_t max_size[2]; - - fh = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); - if ( fh < 0 ) { - ERROR("Couldn't create file: %s\n", filename); - return 1; - } - - gh = H5Gcreate2(fh, "data", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); - if ( gh < 0 ) { - ERROR("Couldn't create group\n"); - H5Fclose(fh); - return 1; - } - - /* Note the "swap" here, according to section 3.2.5, - * "C versus Fortran Dataspaces", of the HDF5 user's guide. */ - size[0] = height; - size[1] = width; - max_size[0] = height; - max_size[1] = width; - sh = H5Screate_simple(2, size, max_size); - - /* Set compression */ - ph = H5Pcreate(H5P_DATASET_CREATE); - H5Pset_chunk(ph, 2, size); - H5Pset_deflate(ph, 3); - - dh = H5Dcreate2(gh, "data", type, sh, - H5P_DEFAULT, ph, H5P_DEFAULT); - if ( dh < 0 ) { - ERROR("Couldn't create dataset\n"); - H5Fclose(fh); - return 1; - } - - /* Muppet check */ - H5Sget_simple_extent_dims(sh, size, max_size); - - r = H5Dwrite(dh, type, H5S_ALL, - H5S_ALL, H5P_DEFAULT, data); - if ( r < 0 ) { - ERROR("Couldn't write data\n"); - H5Dclose(dh); - H5Fclose(fh); - return 1; - } - - H5Pclose(ph); - H5Gclose(gh); - H5Dclose(dh); - H5Fclose(fh); - - return 0; -} - - -static double get_wavelength(struct hdfile *f) -{ - herr_t r; - hid_t dh; - double lambda; - int nm = 1; - - dh = H5Dopen2(f->fh, "/LCLS/photon_wavelength_nm", H5P_DEFAULT); - if ( dh < 0 ) { - dh = H5Dopen2(f->fh, "/LCLS/photon_wavelength_A", H5P_DEFAULT); - if ( dh < 0 ) { - ERROR("Couldn't get photon wavelength from HDF5 file.\n"); - return -1.0; - } - nm = 0; - } - - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &lambda); - H5Dclose(dh); - - if ( r < 0 ) return -1.0; - if ( isnan(lambda) ) return -1.0; - - /* Convert nm -> m */ - if ( nm ) return lambda / 1.0e9; - return lambda / 1.0e10; -} - - -static double get_i0(struct hdfile *f) -{ - herr_t r; - hid_t dh; - double i0; - - dh = H5Dopen2(f->fh, "/LCLS/f_11_ENRC", H5P_DEFAULT); - if ( dh < 0 ) return -1.0; - - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &i0); - H5Dclose(dh); - if ( r < 0 ) return -1.0; - - return i0; -} - - -static void debodge_saturation(struct hdfile *f, struct image *image) -{ - hid_t dh, sh; - hsize_t size[2]; - hsize_t max_size[2]; - int i; - float *buf; - herr_t r; - - dh = H5Dopen2(f->fh, "/processing/hitfinder/peakinfo_saturated", - H5P_DEFAULT); - - if ( dh < 0 ) { - /* This isn't an error */ - return; - } - - sh = H5Dget_space(dh); - if ( sh < 0 ) { - H5Dclose(dh); - ERROR("Couldn't get dataspace for saturation table.\n"); - return; - } - - if ( H5Sget_simple_extent_ndims(sh) != 2 ) { - H5Sclose(sh); - H5Dclose(dh); - return; - } - - H5Sget_simple_extent_dims(sh, size, max_size); - - if ( size[1] != 3 ) { - H5Sclose(sh); - H5Dclose(dh); - ERROR("Saturation table has the wrong dimensions.\n"); - return; - } - - buf = malloc(sizeof(float)*size[0]*size[1]); - if ( buf == NULL ) { - H5Sclose(sh); - H5Dclose(dh); - ERROR("Couldn't reserve memory for saturation table.\n"); - return; - } - r = H5Dread(dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, buf); - if ( r < 0 ) { - ERROR("Couldn't read saturation table.\n"); - free(buf); - return; - } - - for ( i=0; i<size[0]; i++ ) { - - unsigned int x, y; - float val; - - x = buf[3*i+0]; - y = buf[3*i+1]; - val = buf[3*i+2]; - - image->data[x+image->width*y] = val / 5.0; - image->data[x+1+image->width*y] = val / 5.0; - image->data[x-1+image->width*y] = val / 5.0; - image->data[x+image->width*(y+1)] = val / 5.0; - image->data[x+image->width*(y-1)] = val / 5.0; - - } - - free(buf); - H5Sclose(sh); - H5Dclose(dh); -} - - -int hdf5_read(struct hdfile *f, struct image *image, int satcorr) -{ - herr_t r; - float *buf; - uint16_t *flags; - hid_t mask_dh; - - /* Note the "swap" here, according to section 3.2.5, - * "C versus Fortran Dataspaces", of the HDF5 user's guide. */ - image->width = f->ny; - image->height = f->nx; - - buf = malloc(sizeof(float)*f->nx*f->ny); - - r = H5Dread(f->dh, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, buf); - if ( r < 0 ) { - ERROR("Couldn't read data\n"); - free(buf); - return 1; - } - image->data = buf; - - if ( (image->det != NULL) && (image->det->mask != NULL) ) { - - mask_dh = H5Dopen2(f->fh, image->det->mask, H5P_DEFAULT); - if ( mask_dh <= 0 ) { - ERROR("Couldn't open flags\n"); - image->flags = NULL; - } else { - flags = malloc(sizeof(uint16_t)*f->nx*f->ny); - r = H5Dread(mask_dh, H5T_NATIVE_UINT16, H5S_ALL, H5S_ALL, - H5P_DEFAULT, flags); - if ( r < 0 ) { - ERROR("Couldn't read flags\n"); - free(flags); - image->flags = NULL; - } else { - image->flags = flags; - } - H5Dclose(mask_dh); - } - - } - - /* Read wavelength from file */ - image->lambda = get_wavelength(f); - - image->i0 = get_i0(f); - if ( image->i0 < 0.0 ) { - ERROR("Couldn't read incident intensity - using 1.0.\n"); - image->i0 = 1.0; - image->i0_available = 0; - } else { - image->i0_available = 1; - } - - if ( satcorr ) debodge_saturation(f, image); - - return 0; -} - - -static int looks_like_image(hid_t h) -{ - hid_t sh; - hsize_t size[2]; - hsize_t max_size[2]; - - sh = H5Dget_space(h); - if ( sh < 0 ) return 0; - - if ( H5Sget_simple_extent_ndims(sh) != 2 ) { - return 0; - } - - H5Sget_simple_extent_dims(sh, size, max_size); - - if ( ( size[0] > 64 ) && ( size[1] > 64 ) ) return 1; - - return 0; -} - - -double get_value(struct hdfile *f, const char *name) -{ - hid_t dh; - hid_t sh; - hsize_t size; - hsize_t max_size; - hid_t type; - hid_t class; - herr_t r; - double buf; - - dh = H5Dopen2(f->fh, name, H5P_DEFAULT); - if ( dh < 0 ) { - ERROR("Couldn't open data\n"); - return 0.0; - } - - type = H5Dget_type(dh); - class = H5Tget_class(type); - - if ( class != H5T_FLOAT ) { - ERROR("Not a floating point value.\n"); - H5Tclose(type); - H5Dclose(dh); - return 0.0; - } - - sh = H5Dget_space(dh); - if ( H5Sget_simple_extent_ndims(sh) != 1 ) { - ERROR("Not a scalar value.\n"); - H5Tclose(type); - H5Dclose(dh); - return 0.0; - } - - H5Sget_simple_extent_dims(sh, &size, &max_size); - if ( size != 1 ) { - ERROR("Not a scalar value.\n"); - H5Tclose(type); - H5Dclose(dh); - return 0.0; - } - - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &buf); - if ( r < 0 ) { - ERROR("Couldn't read value.\n"); - H5Tclose(type); - H5Dclose(dh); - return 0.0; - } - - return buf; -} - - -struct copy_hdf5_field -{ - char **fields; - int n_fields; - int max_fields; -}; - - -struct copy_hdf5_field *new_copy_hdf5_field_list() -{ - struct copy_hdf5_field *n; - - n = calloc(1, sizeof(struct copy_hdf5_field)); - if ( n == NULL ) return NULL; - - n->max_fields = 32; - n->fields = malloc(n->max_fields*sizeof(char *)); - if ( n->fields == NULL ) { - free(n); - return NULL; - } - - return n; -} - - -void free_copy_hdf5_field_list(struct copy_hdf5_field *n) -{ - int i; - for ( i=0; i<n->n_fields; i++ ) { - free(n->fields[i]); - } - free(n->fields); - free(n); -} - - -void add_copy_hdf5_field(struct copy_hdf5_field *copyme, - const char *name) -{ - assert(copyme->n_fields < copyme->max_fields); /* FIXME */ - - copyme->fields[copyme->n_fields] = strdup(name); - if ( copyme->fields[copyme->n_fields] == NULL ) { - ERROR("Failed to add field for copying '%s'\n", name); - return; - } - - copyme->n_fields++; -} - - -void copy_hdf5_fields(struct hdfile *f, const struct copy_hdf5_field *copyme, - FILE *fh) -{ - int i; - - if ( copyme == NULL ) return; - - for ( i=0; i<copyme->n_fields; i++ ) { - - char *val; - char *field; - - field = copyme->fields[i]; - val = hdfile_get_string_value(f, field); - - if ( field[0] == '/' ) { - fprintf(fh, "hdf5%s = %s\n", field, val); - } else { - fprintf(fh, "hdf5/%s = %s\n", field, val); - } - - free(val); - - } -} - - -char *hdfile_get_string_value(struct hdfile *f, const char *name) -{ - hid_t dh; - hid_t sh; - hsize_t size; - hsize_t max_size; - hid_t type; - hid_t class; - - dh = H5Dopen2(f->fh, name, H5P_DEFAULT); - if ( dh < 0 ) return NULL; - - type = H5Dget_type(dh); - class = H5Tget_class(type); - - if ( class == H5T_STRING ) { - - herr_t r; - char *tmp; - hid_t sh; - - size = H5Tget_size(type); - tmp = malloc(size+1); - - sh = H5Screate(H5S_SCALAR); - - r = H5Dread(dh, type, sh, sh, H5P_DEFAULT, tmp); - if ( r < 0 ) goto fail; - - /* Two possibilities: - * String is already zero-terminated - * String is not terminated. - * Make sure things are done properly... */ - tmp[size] = '\0'; - chomp(tmp); - - return tmp; - - } - - sh = H5Dget_space(dh); - if ( H5Sget_simple_extent_ndims(sh) != 1 ) goto fail; - - H5Sget_simple_extent_dims(sh, &size, &max_size); - if ( size != 1 ) { - H5Dclose(dh); - goto fail; - } - - switch ( class ) { - case H5T_FLOAT : { - - herr_t r; - double buf; - char *tmp; - - r = H5Dread(dh, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &buf); - if ( r < 0 ) goto fail; - - tmp = malloc(256); - snprintf(tmp, 255, "%f", buf); - - return tmp; - - } - case H5T_INTEGER : { - - herr_t r; - int buf; - char *tmp; - - r = H5Dread(dh, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, &buf); - if ( r < 0 ) goto fail; - - tmp = malloc(256); - snprintf(tmp, 255, "%d", buf); - - return tmp; - } - default : { - goto fail; - } - } - -fail: - H5Tclose(type); - H5Dclose(dh); - return NULL; -} - - -char **hdfile_read_group(struct hdfile *f, int *n, const char *parent, - int **p_is_group, int **p_is_image) -{ - hid_t gh; - hsize_t num; - char **res; - int i; - int *is_group; - int *is_image; - H5G_info_t ginfo; - - gh = H5Gopen2(f->fh, parent, H5P_DEFAULT); - if ( gh < 0 ) { - *n = 0; - return NULL; - } - - if ( H5Gget_info(gh, &ginfo) < 0 ) { - /* Whoopsie */ - *n = 0; - return NULL; - } - num = ginfo.nlinks; - *n = num; - if ( num == 0 ) return NULL; - - res = malloc(num*sizeof(char *)); - is_image = malloc(num*sizeof(int)); - is_group = malloc(num*sizeof(int)); - *p_is_image = is_image; - *p_is_group = is_group; - - for ( i=0; i<num; i++ ) { - - char buf[256]; - hid_t dh; - H5I_type_t type; - - H5Lget_name_by_idx(gh, ".", H5_INDEX_NAME, H5_ITER_NATIVE, - i, buf, 255, H5P_DEFAULT); - res[i] = malloc(256); - if ( strlen(parent) > 1 ) { - snprintf(res[i], 255, "%s/%s", parent, buf); - } else { - snprintf(res[i], 255, "%s%s", parent, buf); - } /* ick */ - - is_image[i] = 0; - is_group[i] = 0; - dh = H5Oopen(gh, buf, H5P_DEFAULT); - if ( dh < 0 ) continue; - type = H5Iget_type(dh); - - if ( type == H5I_GROUP ) { - is_group[i] = 1; - } else if ( type == H5I_DATASET ) { - is_image[i] = looks_like_image(dh); - } - H5Oclose(dh); - - } - - return res; -} - - -int hdfile_set_first_image(struct hdfile *f, const char *group) -{ - char **names; - int *is_group; - int *is_image; - int n, i, j; - - names = hdfile_read_group(f, &n, group, &is_group, &is_image); - if ( n == 0 ) return 1; - - for ( i=0; i<n; i++ ) { - - if ( is_image[i] ) { - hdfile_set_image(f, names[i]); - for ( j=0; j<n; j++ ) free(names[j]); - free(is_image); - free(is_group); - free(names); - return 0; - } else if ( is_group[i] ) { - if ( !hdfile_set_first_image(f, names[i]) ) { - for ( j=0; j<n; j++ ) free(names[j]); - free(is_image); - free(is_group); - free(names); - return 0; - } - } - - } - - for ( j=0; j<n; j++ ) free(names[j]); - free(is_image); - free(is_group); - free(names); - - return 1; -} diff --git a/src/hdf5-file.h b/src/hdf5-file.h deleted file mode 100644 index 385e919c..00000000 --- a/src/hdf5-file.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * hdf5-file.h - * - * Read/write HDF5 data files - * - * (c) 2006-2011 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef HDF5_H -#define HDF5_H - -#include <stdint.h> -#include <hdf5.h> - -#include "image.h" - -struct hdfile; - -struct copy_hdf5_field; - - -extern int hdf5_write(const char *filename, const void *data, - int width, int height, int type); - -extern int hdf5_read(struct hdfile *f, struct image *image, int satcorr); - -extern struct hdfile *hdfile_open(const char *filename); -extern int hdfile_set_image(struct hdfile *f, const char *path); -extern int16_t *hdfile_get_image_binned(struct hdfile *hdfile, - int binning, int16_t *maxp); -extern char **hdfile_read_group(struct hdfile *f, int *n, const char *parent, - int **p_is_group, int **p_is_image); -extern int hdfile_set_first_image(struct hdfile *f, const char *group); -extern void hdfile_close(struct hdfile *f); - -extern char *hdfile_get_string_value(struct hdfile *f, const char *name); -extern int get_peaks(struct image *image, struct hdfile *f, const char *p); -extern double get_value(struct hdfile *f, const char *name); - -extern struct copy_hdf5_field *new_copy_hdf5_field_list(void); -extern void free_copy_hdf5_field_list(struct copy_hdf5_field *f); -extern void copy_hdf5_fields(struct hdfile *f, - const struct copy_hdf5_field *copyme, FILE *fh); -extern void add_copy_hdf5_field(struct copy_hdf5_field *copyme, - const char *name); - - -#endif /* HDF5_H */ diff --git a/src/image.h b/src/image.h index 4d4ac2d7..e21ebe85 100644 --- a/src/image.h +++ b/src/image.h @@ -21,10 +21,10 @@ #include <complex.h> #include <sys/types.h> -#include "utils.h" -#include "cell.h" -#include "detector.h" -#include "reflist.h" +#include <utils.h> +#include <cell.h> +#include <detector.h> +#include <reflist.h> #define MAX_CELL_CANDIDATES (32) diff --git a/src/list_tmp.h b/src/list_tmp.h deleted file mode 100644 index a524b2f9..00000000 --- a/src/list_tmp.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Template for creating indexed 3D lists of a given type, usually indexed - * as signed h,k,l values where -INDMAX<={h,k,l}<=+INDMAX. - * - * These are used, for example, for: - * - a list of 'double complex' values for storing structure factors, - * - a list of 'double' values for storing reflection intensities, - * - a list of 'unsigned int' values for counts of some sort. - * - * When LABEL and TYPE are #defined appropriately, including this header - * defines functions such as: - * - new_list_<LABEL>(), for creating a new list of the given type, - * - set_<LABEL>(), for setting a value in a list, - * - lookup_<LABEL>(), for retrieving values from a list, - * ..and so on. - * - * See src/utils.h for more information. - * - */ - -#include <stdio.h> - -#define ERROR_T(...) fprintf(stderr, __VA_ARGS__) - -static inline void LABEL(integrate)(TYPE *ref, signed int h, - signed int k, signed int l, - TYPE i) -{ - int idx; - - if ( (abs(h) > INDMAX) || (abs(k) > INDMAX) || (abs(l) > INDMAX) ) { - ERROR_T("\nReflection %i %i %i is out of range!\n", h, k, l); - ERROR_T("You need to re-configure INDMAX and re-run.\n"); - exit(1); - } - - if ( h < 0 ) h += IDIM; - if ( k < 0 ) k += IDIM; - if ( l < 0 ) l += IDIM; - - idx = h + (IDIM*k) + (IDIM*IDIM*l); - ref[idx] += i; -} - - -static inline void LABEL(set)(TYPE *ref, signed int h, - signed int k, signed int l, - TYPE i) -{ - int idx; - - if ( (abs(h) > INDMAX) || (abs(k) > INDMAX) || (abs(l) > INDMAX) ) { - ERROR_T("\nReflection %i %i %i is out of range!\n", h, k, l); - ERROR_T("You need to re-configure INDMAX and re-run.\n"); - exit(1); - } - - if ( h < 0 ) h += IDIM; - if ( k < 0 ) k += IDIM; - if ( l < 0 ) l += IDIM; - - idx = h + (IDIM*k) + (IDIM*IDIM*l); - ref[idx] = i; -} - - -static inline TYPE LABEL(lookup)(const TYPE *ref, signed int h, - signed int k, signed int l) -{ - int idx; - - if ( (abs(h) > INDMAX) || (abs(k) > INDMAX) || (abs(l) > INDMAX) ) { - ERROR_T("\nReflection %i %i %i is out of range!\n", h, k, l); - ERROR_T("You need to re-configure INDMAX and re-run.\n"); - exit(1); - } - - if ( h < 0 ) h += IDIM; - if ( k < 0 ) k += IDIM; - if ( l < 0 ) l += IDIM; - - idx = h + (IDIM*k) + (IDIM*IDIM*l); - return ref[idx]; -} - - -static inline TYPE *LABEL(new_list)(void) -{ - TYPE *r; - size_t r_size; - r_size = IDIM*IDIM*IDIM*sizeof(TYPE); - r = malloc(r_size); - memset(r, 0, r_size); - return r; -} - - -static inline void LABEL(zero_list)(TYPE *ref) -{ - memset(ref, 0, IDIM*IDIM*IDIM*sizeof(TYPE)); -} - - -#undef LABEL -#undef TYPE -#undef ERROR_T diff --git a/src/partial_sim.c b/src/partial_sim.c index 9f6a4015..c339dba9 100644 --- a/src/partial_sim.c +++ b/src/partial_sim.c @@ -425,7 +425,7 @@ int main(int argc, char *argv[]) image.lambda = ph_en_to_lambda(eV_to_J(beam->photon_energy)); image.div = beam->divergence; image.bw = beam->bandwidth; - image.profile_radius = 0.003e9; + image.profile_radius = 0.01e9; image.i0_available = 0; image.filename = malloc(256); image.copyme = NULL; diff --git a/src/reflist.c b/src/reflist.c deleted file mode 100644 index 18856c67..00000000 --- a/src/reflist.c +++ /dev/null @@ -1,1048 +0,0 @@ -/* - * reflist.c - * - * Fast reflection/peak list - * - * (c) 2011 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#include <stdlib.h> -#include <assert.h> -#include <stdio.h> -#include <pthread.h> - -#include "reflist.h" -#include "utils.h" - -/** - * SECTION:reflist - * @short_description: The fast reflection list - * @title: RefList - * @section_id: - * @see_also: - * @include: "reflist.h" - * @Image: - * - * The fast reflection list stores reflections in an RB-tree indexed - * by the Miller indices h, k and l. Any reflection can be found in a - * length of time which scales logarithmically with the number of reflections in - * the list. - * - * A RefList can contain any number of reflections, and can store more than - * one reflection with a given set of indices, for example when two distinct - * reflections are to be stored according to their asymmetric indices. - * - * There are getters and setters which can be used to get and set values for an - * individual reflection. The reflection list does not calculate any values, - * only stores what it was given earlier. As such, you will need to carefully - * examine which fields your prior processing steps have filled in. - */ - - -struct _refldata { - - /* Symmetric indices (i.e. the "real" indices) */ - signed int hs; - signed int ks; - signed int ls; - - /* Partiality and related geometrical stuff */ - double r1; /* First excitation error */ - double r2; /* Second excitation error */ - double p; /* Partiality */ - int clamp1; /* Clamp status for r1 */ - int clamp2; /* Clamp status for r2 */ - - /* Location in image */ - double fs; - double ss; - - /* The distance from the exact Bragg position to the coordinates - * given above. */ - double excitation_error; - - /* Non-zero if this reflection can be used for scaling */ - int scalable; - - /* Non-zero if this reflection should be used as a "guide star" for - * post refinement */ - int refinable; - - /* Intensity */ - double intensity; - double esd_i; - - /* Phase */ - double phase; - int have_phase; - - /* Redundancy */ - int redundancy; - - /* User-specified temporary values */ - double temp1; - double temp2; -}; - - -enum _nodecol { - RED, - BLACK -}; - - -struct _reflection { - - /* Listy stuff */ - unsigned int serial; /* Unique serial number, key */ - struct _reflection *child[2]; /* Child nodes */ - struct _reflection *next; /* Next and previous in doubly linked */ - struct _reflection *prev; /* list of duplicate reflections */ - enum _nodecol col; /* Colour (red or black) */ - - /* Payload */ - pthread_mutex_t lock; /* Protects the contents of "data" */ - struct _refldata data; -}; - - -struct _reflist { - - struct _reflection *head; - struct _reflection *tail; - -}; - - -#define SERIAL(h, k, l) ((((h)+256)<<18) + (((k)+256)<<9) + ((l)+256)) -#define GET_H(serial) ((((serial) & 0xfffc0000)>>18)-256) -#define GET_K(serial) ((((serial) & 0x0003fe00)>>9)-256) -#define GET_L(serial) (((serial) & 0x000001ff)-256) - -/**************************** Creation / deletion *****************************/ - -static Reflection *new_node(unsigned int serial) -{ - Reflection *new; - - new = calloc(1, sizeof(struct _reflection)); - new->serial = serial; - new->next = NULL; - new->prev = NULL; - new->child[0] = NULL; - new->child[1] = NULL; - new->col = RED; - pthread_mutex_init(&new->lock, NULL); - - return new; -} - - -/** - * reflist_new: - * - * Creates a new reflection list. - * - * Returns: the new reflection list, or NULL on error. - */ -RefList *reflist_new() -{ - RefList *new; - - new = malloc(sizeof(struct _reflist)); - if ( new == NULL ) return NULL; - - new->head = NULL; - - return new; -} - - -/** - * reflection_new: - * @h: The h index of the new reflection - * @k: The k index of the new reflection - * @l: The l index of the new reflection - * - * Creates a new individual reflection. You'll probably want to use - * add_refl_to_list() at some later point. - */ -Reflection *reflection_new(signed int h, signed int k, signed int l) -{ - return new_node(SERIAL(h, k, l)); -} - - -/** - * reflection_free: - * @refl: The reflection to free. - * - * Destroys an individual reflection. - */ -void reflection_free(Reflection *refl) -{ - pthread_mutex_destroy(&refl->lock); - free(refl); -} - - -static void recursive_free(Reflection *refl) -{ - if ( refl->child[0] != NULL ) recursive_free(refl->child[0]); - if ( refl->child[1] != NULL ) recursive_free(refl->child[1]); - - while ( refl != NULL ) { - Reflection *next = refl->next; - reflection_free(refl); - refl = next; - } -} - - -/** - * reflist_free: - * @list: The reflection list to free. - * - * Destroys a reflection list. - */ -void reflist_free(RefList *list) -{ - if ( list == NULL ) return; - if ( list->head != NULL ) { - recursive_free(list->head); - } /* else empty list */ - free(list); -} - - -/********************************** Search ************************************/ - -/** - * find_refl: - * @list: The reflection list to search in - * @h: The 'h' index to search for - * @k: The 'k' index to search for - * @l: The 'l' index to search for - * - * This function finds the first reflection in 'list' with the given indices. - * - * Since a %RefList can contain multiple reflections with the same indices, you - * may need to use next_found_refl() to get the other reflections. - * - * Returns: The found reflection, or NULL if no reflection with the given - * indices could be found. - **/ -Reflection *find_refl(const RefList *list, - signed int h, signed int k, signed int l) -{ - unsigned int search = SERIAL(h, k, l); - Reflection *refl; - - if ( list->head == NULL ) return NULL; - - /* Indices greater than or equal to 256 are filtered out when - * reflections are added, so don't even bother looking. - * (also, looking for such reflections causes trouble because the search - * serial number would be invalid) */ - if ( abs(h) >= 256 ) return NULL; - if ( abs(k) >= 256 ) return NULL; - if ( abs(l) >= 256 ) return NULL; - - refl = list->head; - - while ( refl != NULL ) { - - if ( refl->serial == search ) { - - assert(search == refl->serial); - assert(h == GET_H(refl->serial)); - assert(k == GET_K(refl->serial)); - assert(l == GET_L(refl->serial)); - return refl; - - } else { - - int dir = search > refl->serial; - if ( refl->child[dir] != NULL ) { - refl = refl->child[dir]; - } else { - /* Hit the bottom of the tree */ - return NULL; - } - - } - - } - - return NULL; -} - - -/** - * next_found_refl: - * @refl: A reflection returned by find_refl() or next_found_refl() - * - * This function returns the next reflection in @refl's list with the same - * indices. - * - * Returns: The found reflection, or NULL if there are no more reflections with - * the same indices. - **/ -Reflection *next_found_refl(Reflection *refl) -{ - if ( refl->next != NULL ) assert(refl->serial == refl->next->serial); - - return refl->next; /* Well, that was easy... */ -} - - -/********************************** Getters ***********************************/ - -/** - * get_excitation_error: - * @refl: A %Reflection - * - * Returns: The excitation error for the reflection. - **/ -double get_excitation_error(const Reflection *refl) -{ - return refl->data.excitation_error; -} - - -/** - * get_detector_pos: - * @refl: A %Reflection - * @fs: Location at which to store the fast scan offset of the reflection - * @ss: Location at which to store the slow scan offset of the reflection - * - **/ -void get_detector_pos(const Reflection *refl, double *fs, double *ss) -{ - *fs = refl->data.fs; - *ss = refl->data.ss; -} - - -/** - * get_indices: - * @refl: A %Reflection - * @h: Location at which to store the 'h' index of the reflection - * @k: Location at which to store the 'k' index of the reflection - * @l: Location at which to store the 'l' index of the reflection - * - **/ -void get_indices(const Reflection *refl, - signed int *h, signed int *k, signed int *l) -{ - *h = GET_H(refl->serial); - *k = GET_K(refl->serial); - *l = GET_L(refl->serial); -} - - -/** - * get_symmetric_indices: - * @refl: A %Reflection - * @hs: Location at which to store the 'h' index of the reflection - * @ks: Location at which to store the 'k' index of the reflection - * @ls: Location at which to store the 'l' index of the reflection - * - * This function gives the symmetric indices, that is, the "real" indices before - * squashing down to the asymmetric reciprocal unit. This may be useful if the - * list is indexed according to the asymmetric indices, but you still need - * access to the symmetric version. This happens during post-refinement. - * - **/ -void get_symmetric_indices(const Reflection *refl, - signed int *hs, signed int *ks, - signed int *ls) -{ - *hs = refl->data.hs; - *ks = refl->data.ks; - *ls = refl->data.ls; -} - - -/** - * get_partiality: - * @refl: A %Reflection - * - * Returns: The partiality of the reflection. - **/ -double get_partiality(const Reflection *refl) -{ - return refl->data.p; -} - - -/** - * get_intensity: - * @refl: A %Reflection - * - * Returns: The intensity of the reflection. - **/ -double get_intensity(const Reflection *refl) -{ - return refl->data.intensity; -} - - -/** - * get_partial: - * @refl: A %Reflection - * @r1: Location at which to store the first excitation error - * @r2: Location at which to store the second excitation error - * @p: Location at which to store the partiality - * @clamp_low: Location at which to store the first clamp status - * @clamp_high: Location at which to store the second clamp status - * - * This function is used during post refinement (in conjunction with - * set_partial()) to get access to the details of the partiality calculation. - * - **/ -void get_partial(const Reflection *refl, double *r1, double *r2, double *p, - int *clamp_low, int *clamp_high) -{ - *r1 = refl->data.r1; - *r2 = refl->data.r2; - *p = get_partiality(refl); - *clamp_low = refl->data.clamp1; - *clamp_high = refl->data.clamp2; -} - - -/** - * get_scalable: - * @refl: A %Reflection - * - * Returns: non-zero if this reflection can be scaled. - * - **/ -int get_scalable(const Reflection *refl) -{ - return refl->data.scalable; -} - - -/** - * get_refinable: - * @refl: A %Reflection - * - * Returns: non-zero if this reflection can be used for post refinement. - * - **/ -int get_refinable(const Reflection *refl) -{ - return refl->data.refinable; -} - - -/** - * get_redundancy: - * @refl: A %Reflection - * - * The redundancy of the reflection is the number of measurements that have been - * made of it. Note that a redundancy of zero may have a special meaning, such - * as that the reflection was impossible to integrate. Note further that each - * reflection in the list has its own redundancy, even if there are multiple - * copies of the reflection in the list. The total number of reflection - * measurements should always be the sum of the redundancies in the entire list. - * - * Returns: the number of measurements of this reflection. - * - **/ -int get_redundancy(const Reflection *refl) -{ - return refl->data.redundancy; -} - - -/** - * get_esd_intensity: - * @refl: A %Reflection - * - * Returns: the standard error in the intensity measurement (as returned by - * get_intensity()) for this reflection. - * - **/ -double get_esd_intensity(const Reflection *refl) -{ - return refl->data.esd_i; -} - - -/** - * get_phase: - * @refl: A %Reflection - * @have_phase: Place to store a non-zero value if the phase is set, or NULL. - * - * Returns: the phase for this reflection. - * - **/ -double get_phase(const Reflection *refl, int *have_phase) -{ - if ( have_phase != NULL ) *have_phase = refl->data.have_phase; - return refl->data.phase; -} - - -/** - * get_temp1: - * @refl: A %Reflection - * - * The temporary values can be used according to the needs of the calling - * program. - * - * Returns: the first temporary value for this reflection. - * - **/ -double get_temp1(const Reflection *refl) -{ - return refl->data.temp1; -} - - -/** - * get_temp2: - * @refl: A %Reflection - * - * The temporary values can be used according to the needs of the calling - * program. - * - * Returns: the second temporary value for this reflection. - * - **/ -double get_temp2(const Reflection *refl) -{ - return refl->data.temp2; -} - - -/********************************** Setters ***********************************/ - -/** - * copy_data: - * @to: %Reflection to copy data into - * @from: %Reflection to copy data from - * - * This function is used to copy the data (which is everything listed above in - * the list of getters and setters, apart from the indices themselves) from one - * reflection to another. This might be used when creating a new list from an - * old one, perhaps using the asymmetric indices instead of the raw indices for - * the new list. - * - **/ -void copy_data(Reflection *to, const Reflection *from) -{ - memcpy(&to->data, &from->data, sizeof(struct _refldata)); -} - - -/** - * set_detector_pos: - * @refl: A %Reflection - * @exerr: The excitation error for this reflection - * @fs: The fast scan offset of the reflection - * @ss: The slow scan offset of the reflection - * - **/ -void set_detector_pos(Reflection *refl, double exerr, double fs, double ss) -{ - refl->data.excitation_error = exerr; - refl->data.fs = fs; - refl->data.ss = ss; -} - - -/** - * set_partial: - * @refl: A %Reflection - * @r1: The first excitation error - * @r2: The second excitation error - * @p: The partiality - * @clamp_low: The first clamp status - * @clamp_high: The second clamp status - * - * This function is used during post refinement (in conjunction with - * get_partial()) to get access to the details of the partiality calculation. - * - **/ -void set_partial(Reflection *refl, double r1, double r2, double p, - double clamp_low, double clamp_high) -{ - refl->data.r1 = r1; - refl->data.r2 = r2; - refl->data.p = p; - refl->data.clamp1 = clamp_low; - refl->data.clamp2 = clamp_high; -} - - -/** - * set_int: - * @refl: A %Reflection - * @intensity: The intensity for the reflection. - * - * Set the intensity for the reflection. Note that retrieval is done with - * get_intensity(). - **/ -void set_int(Reflection *refl, double intensity) -{ - refl->data.intensity = intensity; -} - - -/** - * set_scalable: - * @refl: A %Reflection - * @scalable: Non-zero if this reflection should be scaled. - * - **/ -void set_scalable(Reflection *refl, int scalable) -{ - refl->data.scalable = scalable; -} - - -/** - * set_refinable: - * @refl: A %Reflection - * @refinable: Non-zero if this reflection can be used for post refinement. - * - **/ -void set_refinable(Reflection *refl, int refinable) -{ - refl->data.refinable = refinable; -} - - -/** - * set_redundancy: - * @refl: A %Reflection - * @red: New redundancy for the reflection - * - * The redundancy of the reflection is the number of measurements that have been - * made of it. Note that a redundancy of zero may have a special meaning, such - * as that the reflection was impossible to integrate. Note further that each - * reflection in the list has its own redundancy, even if there are multiple - * copies of the reflection in the list. The total number of reflection - * measurements should always be the sum of the redundancies in the entire list. - * - **/ -void set_redundancy(Reflection *refl, int red) -{ - refl->data.redundancy = red; -} - - -/** - * set_esd_intensity: - * @refl: A %Reflection - * @esd: New standard error for this reflection's intensity measurement - * - **/ -void set_esd_intensity(Reflection *refl, double esd) -{ - refl->data.esd_i = esd; -} - - -/** - * set_ph: - * @refl: A %Reflection - * @phase: New phase for the reflection - * - **/ -void set_ph(Reflection *refl, double phase) -{ - refl->data.phase = phase; - refl->data.have_phase = 1; -} - - -/** - * set_symmetric_indices: - * @refl: A %Reflection - * @hs: The 'h' index of the reflection - * @ks: The 'k' index of the reflection - * @ls: The 'l' index of the reflection - * - * This function gives the symmetric indices, that is, the "real" indices before - * squashing down to the asymmetric reciprocal unit. This may be useful if the - * list is indexed according to the asymmetric indices, but you still need - * access to the symmetric version. This happens during post-refinement. - * - **/ -void set_symmetric_indices(Reflection *refl, - signed int hs, signed int ks, signed int ls) -{ - refl->data.hs = hs; - refl->data.ks = ks; - refl->data.ls = ls; -} - - -/** - * set_temp1 - * @refl: A %Reflection - * @temp: New temporary value for the reflection - * - * The temporary values can be used according to the needs of the calling - * program. - * - **/ -void set_temp1(Reflection *refl, double temp) -{ - refl->data.temp1 = temp; -} - - -/** - * set_temp2 - * @refl: A %Reflection - * @temp: New temporary value for the reflection - * - * The temporary values can be used according to the needs of the calling - * program. - * - **/ -void set_temp2(Reflection *refl, double temp) -{ - refl->data.temp2 = temp; -} - - -/********************************* Insertion **********************************/ - -static Reflection *rotate_once(Reflection *refl, int dir) -{ - Reflection *s = refl->child[!dir]; - - refl->child[!dir] = s->child[dir]; - s->child[dir] = refl; - - refl->col = RED; - s->col = BLACK; - - return s; -} - - -static Reflection *rotate_twice(Reflection *refl, int dir) -{ - refl->child[!dir] = rotate_once(refl->child[!dir], !dir); - return rotate_once(refl, dir); -} - - -static int is_red(Reflection *refl) -{ - return (refl != NULL) && (refl->col == RED); -} - - -static Reflection *insert_node(Reflection *refl, Reflection *new) -{ - if ( refl == NULL ) { - - refl = new; - - } else { - - int dir; - Reflection *rcd; - - assert(new->serial != refl->serial); - dir = new->serial > refl->serial; - refl->child[dir] = insert_node(refl->child[dir], new); - - rcd = refl->child[dir]; - if ( is_red(rcd) ) { - - if ( is_red(refl->child[!dir]) ) { - - refl->col = RED; - refl->child[0]->col = BLACK; - refl->child[1]->col = BLACK; - - } else { - - if ( is_red(rcd->child[dir] ) ) { - refl = rotate_once(refl, !dir); - } else if ( is_red(rcd->child[!dir] ) ) { - refl = rotate_twice(refl, !dir); - } - - } - } - - } - - return refl; -} - - -/** - * add_refl - * @list: A %RefList - * @h: The 'h' index of the reflection - * @k: The 'k' index of the reflection - * @l: The 'l' index of the reflection - * - * Adds a new reflection to @list. Note that the implementation allows there to - * be multiple reflections with the same indices in the list, so this function - * should succeed even if the given indices already feature in the list. - * - * Returns: The newly created reflection, or NULL on failure. - * - **/ -Reflection *add_refl(RefList *list, signed int h, signed int k, signed int l) -{ - Reflection *new; - Reflection *f; - - assert(abs(h)<256); - assert(abs(k)<256); - assert(abs(l)<256); - - new = new_node(SERIAL(h, k, l)); - if ( new == NULL ) return NULL; - - f = find_refl(list, h, k, l); - if ( f == NULL ) { - - list->head = insert_node(list->head, new); - list->head->col = BLACK; - - } else { - - /* New reflection is identical to a previous one */ - while ( f->next != NULL ) { - f = f->next; - } - f->next = new; - new->prev = f; - } - - return new; -} - - -/** - * add_refl_to_list - * @refl: A %Reflection - * @list: A %RefList - * - * Adds a reflection to @list. The reflection that actually gets added will be - * a newly created one, and all the data will be copied across. The original - * reflection will be destroyed and the new reflection returned. - * - * Returns: The newly created reflection, or NULL on failure. - * - **/ -Reflection *add_refl_to_list(Reflection *refl, RefList *list) -{ - signed int h, k, l; - Reflection *r_added; - - get_indices(refl, &h, &k, &l); - r_added = add_refl(list, h, k, l); - if ( r_added == NULL ) return NULL; - - copy_data(r_added, refl); - reflection_free(refl); - - return r_added; -} - - -/********************************* Iteration **********************************/ - -struct _reflistiterator { - - int stack_size; - int stack_ptr; - Reflection **stack; - -}; - - -/** - * first_refl: - * @list: A %RefList to iterate over - * @piter: Address at which to store a %RefListIterator - * - * This function sets up the state required for iteration over the entire list, - * and then returns the first reflection in the list. An iterator object will - * be created and its address stored at the location given in piter. - * - * Returns: the first reflection in the list. - * - **/ -Reflection *first_refl(RefList *list, RefListIterator **piter) -{ - RefListIterator *iter; - - iter = malloc(sizeof(struct _reflistiterator)); - iter->stack_size = 32; - iter->stack = malloc(iter->stack_size*sizeof(Reflection *)); - iter->stack_ptr = 0; - *piter = iter; - - Reflection *refl = list->head; - - do { - - if ( refl != NULL ) { - iter->stack[iter->stack_ptr++] = refl; - if ( iter->stack_ptr == iter->stack_size ) { - iter->stack_size += 32; - iter->stack = realloc(iter->stack, - iter->stack_size*sizeof(Reflection *)); - } - refl = refl->child[0]; - continue; - } - - if ( iter->stack_ptr == 0 ) { - free(iter->stack); - free(iter); - return NULL; - } - - refl = iter->stack[--iter->stack_ptr]; - - return refl; - - } while ( 1 ); -} - - -/** - * next_refl: - * @refl: A reflection - * @iter: A %RefListIterator - * - * This function looks up the next reflection in the list that was given earlier - * to first_refl(). - * - * Returns: the next reflection in the list, or NULL if no more. - * - **/ -Reflection *next_refl(Reflection *refl, RefListIterator *iter) -{ - int returned = 1; - - do { - - if ( returned ) refl = refl->child[1]; - returned = 0; - - if ( refl != NULL ) { - - iter->stack[iter->stack_ptr++] = refl; - if ( iter->stack_ptr == iter->stack_size ) { - iter->stack_size += 32; - iter->stack = realloc(iter->stack, - iter->stack_size*sizeof(Reflection *)); - } - refl = refl->child[0]; - continue; - - } - if ( iter->stack_ptr == 0 ) { - free(iter->stack); - free(iter); - return NULL; - } - - return iter->stack[--iter->stack_ptr]; - - } while ( 1 ); -} - - -/*********************************** Voodoo ***********************************/ - -static int recursive_depth(Reflection *refl) -{ - int depth_left, depth_right; - - if ( refl == NULL ) return 0; - - depth_left = recursive_depth(refl->child[0]); - depth_right = recursive_depth(refl->child[1]); - - return 1 + biggest(depth_left, depth_right); -} - - -static int recursive_count(Reflection *refl) -{ - int count_left, count_right; - - if ( refl == NULL ) return 0; - - count_left = recursive_count(refl->child[0]); - count_right = recursive_count(refl->child[1]); - - return 1 + count_left + count_right; -} - - -/** - * num_reflections: - * @list: A %RefList - * - * Returns: the number of reflections in @list. - * - **/ -int num_reflections(RefList *list) -{ - return recursive_count(list->head); -} - - -/** - * tree_depth: - * @list: A %RefList - * - * If the depth of the tree is more than about 20, access to the list will be - * slow. This should never happen. - * - * Returns: the depth of the RB-tree used internally to represent @list. - * - **/ -int tree_depth(RefList *list) -{ - return recursive_depth(list->head); -} - - -/** - * lock_reflection: - * @refl: A %Reflection - * - * Acquires a lock on the reflection. - */ -void lock_reflection(Reflection *refl) -{ - pthread_mutex_lock(&refl->lock); -} - - -/** - * unlock_reflection: - * @refl: A %Reflection - * - * Releases a lock on the reflection. - */ -void unlock_reflection(Reflection *refl) -{ - pthread_mutex_unlock(&refl->lock); -} diff --git a/src/reflist.h b/src/reflist.h deleted file mode 100644 index 955db69b..00000000 --- a/src/reflist.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * reflist.h - * - * Fast reflection/peak list - * - * (c) 2011 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifndef REFLIST_H -#define REFLIST_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -/** - * RefList: - * - * A %RefList represents a list of Bragg reflections. - * - * This data structure is opaque. You must use the available accessor functions - * to read and write its contents. - * - **/ -typedef struct _reflist RefList; - -/** - * Reflection: - * - * A %Reflection represents a single Bragg reflection. - * - * This data structure is opaque. You must use the available accessor functions - * to read and write its contents. - * - **/ -typedef struct _reflection Reflection; - -/** - * RefListIterator: - * - * A %RefListIterator is an opaque data type used when iterating over a - * %RefList. - * - **/ -typedef struct _reflistiterator RefListIterator; - -/* Creation/deletion */ -extern RefList *reflist_new(void); -extern void reflist_free(RefList *list); -extern Reflection *reflection_new(signed int h, signed int k, signed int l); -extern void reflection_free(Reflection *refl); - -/* Search */ -extern Reflection *find_refl(const RefList *list, signed int h, signed int k, signed int l); -extern Reflection *next_found_refl(Reflection *refl); - -/* Get */ -extern double get_excitation_error(const Reflection *refl); -extern void get_detector_pos(const Reflection *refl, double *fs, double *ss); -extern double get_partiality(const Reflection *refl); -extern void get_indices(const Reflection *refl, - signed int *h, signed int *k, signed int *l); -extern void get_symmetric_indices(const Reflection *refl, - signed int *hs, signed int *ks, - signed int *ls); -extern double get_intensity(const Reflection *refl); -extern void get_partial(const Reflection *refl, double *r1, double *r2, - double *p, int *clamp_low, int *clamp_high); -extern int get_scalable(const Reflection *refl); -extern int get_refinable(const Reflection *refl); -extern int get_redundancy(const Reflection *refl); -extern double get_temp1(const Reflection *refl); -extern double get_temp2(const Reflection *refl); -extern double get_esd_intensity(const Reflection *refl); -extern double get_phase(const Reflection *refl, int *have_phase); - -/* Set */ -extern void copy_data(Reflection *to, const Reflection *from); -extern void set_detector_pos(Reflection *refl, double exerr, - double fs, double ss); -extern void set_partial(Reflection *refl, double r1, double r2, double p, - double clamp_low, double clamp_high); -extern void set_int(Reflection *refl, double intensity); -extern void set_scalable(Reflection *refl, int scalable); -extern void set_refinable(Reflection *refl, int refinable); -extern void set_redundancy(Reflection *refl, int red); -extern void set_temp1(Reflection *refl, double temp); -extern void set_temp2(Reflection *refl, double temp); -extern void set_esd_intensity(Reflection *refl, double esd); -extern void set_ph(Reflection *refl, double phase); -extern void set_symmetric_indices(Reflection *refl, - signed int hs, signed int ks, signed int ls); - -/* Insertion */ -extern Reflection *add_refl(RefList *list, - signed int h, signed int k, signed int l); -extern Reflection *add_refl_to_list(Reflection *refl, RefList *list); - -/* Iteration */ -extern Reflection *first_refl(RefList *list, RefListIterator **piter); -extern Reflection *next_refl(Reflection *refl, RefListIterator *iter); - -/* Misc */ -extern int num_reflections(RefList *list); -extern int tree_depth(RefList *list); -extern void lock_reflection(Reflection *refl); -extern void unlock_reflection(Reflection *refl); - -#endif /* REFLIST_H */ diff --git a/src/scaling-report.c b/src/scaling-report.c index b499e59d..32791bbc 100644 --- a/src/scaling-report.c +++ b/src/scaling-report.c @@ -234,7 +234,7 @@ static void partiality_graph(cairo_t *cr, const struct image *images, int n, Ipart = get_intensity(refl); Ifull = get_intensity(f); - if ( Ifull < 10 ) continue; /* FIXME: Ugh */ + //if ( Ifull < 10 ) continue; /* FIXME: Ugh */ pobs = Ipart/(images[i].osf*Ifull); pcalc = get_partiality(refl); diff --git a/src/thread-pool.c b/src/thread-pool.c deleted file mode 100644 index 0ae26e17..00000000 --- a/src/thread-pool.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * thread-pool.c - * - * A thread pool implementation - * - * (c) 2006-2011 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -#include <stdarg.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <pthread.h> -#include <assert.h> - -#ifdef HAVE_CPU_AFFINITY -#include <sched.h> -#endif - - -#include "utils.h" - - -/** - * SECTION:thread-pool - * @short_description: The thread pool - * @title: The thread pool - * @section_id: - * @see_also: - * @include: "thread-pool.h" - * @Image: - * - * The thread pool helps when running many tasks in parallel. It takes care of - * starting and stopping threads, and presents a relatively simple interface to - * the individual programs. - */ - -/* ------------------------------ CPU affinity ------------------------------ */ - -#ifdef HAVE_CPU_AFFINITY - -static void set_affinity(int n, int cpu_num, int cpu_groupsize, int cpu_offset) -{ - cpu_set_t c; - int group; - int n_cpu_groups; - int i; - - if ( cpu_num == 0 ) return; - - CPU_ZERO(&c); - - /* Work out which group this thread belongs to */ - group = (n / cpu_groupsize) + cpu_offset; - - /* Work out which CPUs should be used for this group */ - n_cpu_groups = cpu_num / cpu_groupsize; - group = group % n_cpu_groups; - - /* Set flags */ - for ( i=0; i<cpu_groupsize; i++ ) { - - int cpu = cpu_groupsize*group + i; - - CPU_SET(cpu, &c); - - } - - if ( sched_setaffinity(0, sizeof(cpu_set_t), &c) ) { - - /* Cannot use ERROR() just yet */ - fprintf(stderr, "%i: Failed to set CPU affinity.\n", n); - - } -} - -#else /* HAVE_CPU_AFFINITY */ - -static void set_affinity(int n, int cpu_num, int cpu_groupsize, int cpu_offset) -{ - /* Do absolutely nothing */ -} - -#endif /* HAVE_CPU_AFFINITY */ - - -/* --------------------------- Status label stuff --------------------------- */ - -static int use_status_labels = 0; -static pthread_key_t status_label_key; -pthread_mutex_t stderr_lock = PTHREAD_MUTEX_INITIALIZER; - -struct worker_args -{ - struct task_queue_range *tqr; - struct task_queue *tq; - int id; - int cpu_num; - int cpu_groupsize; - int cpu_offset; -}; - - -signed int get_status_label() -{ - int *cookie; - - if ( !use_status_labels ) { - return -1; - } - - cookie = pthread_getspecific(status_label_key); - return *cookie; -} - - -struct task_queue -{ - pthread_mutex_t lock; - - int n_started; - int n_completed; - int max; - - void *(*get_task)(void *); - void (*finalise)(void *, void *); - void *queue_args; - void (*work)(void *, int); -}; - - -static void *task_worker(void *pargsv) -{ - struct worker_args *w = pargsv; - struct task_queue *q = w->tq; - int *cookie; - - set_affinity(w->id, w->cpu_num, w->cpu_groupsize, w->cpu_offset); - - cookie = malloc(sizeof(int)); - *cookie = w->id; - pthread_setspecific(status_label_key, cookie); - - free(w); - - do { - - void *task; - int cookie; - - /* Get a task */ - pthread_mutex_lock(&q->lock); - if ( (q->max) && (q->n_started >= q->max) ) { - pthread_mutex_unlock(&q->lock); - break; - } - task = q->get_task(q->queue_args); - - /* No more tasks? */ - if ( task == NULL ) { - pthread_mutex_unlock(&q->lock); - break; - } - - q->n_started++; - pthread_mutex_unlock(&q->lock); - - cookie = *(int *)pthread_getspecific(status_label_key); - q->work(task, cookie); - - /* Update totals etc */ - pthread_mutex_lock(&q->lock); - q->n_completed++; - if ( q->finalise ) { - q->finalise(q->queue_args, task); - } - pthread_mutex_unlock(&q->lock); - - } while ( 1 ); - - free(cookie); - - return NULL; -} - - -/** - * run_threads: - * @n_threads: The number of threads to run in parallel - * @work: The function to be called to do the work - * @get_task: The function which will determine the next unassigned task - * @final: The function which will be called to clean up after a task - * @queue_args: A pointer to any data required to determine the next task - * @max: Stop calling get_task after starting this number of jobs - * @cpu_num: The number of CPUs in the system - * @cpu_groupsize: The group size into which the CPUs are grouped - * @cpu_offset: The CPU group number at which to start pinning threads - * - * 'get_task' will be called every time a worker is idle. It returns either - * NULL, indicating that no further work is available, or a pointer which will - * be passed to 'work'. - * - * 'final' will be called once per image, and will be given both queue_args - * and the last task pointer. - * - * 'get_task' and 'final' will be called only under lock, and so do NOT need to - * be re-entrant or otherwise thread safe. 'work', of course, needs to be - * thread safe. - * - * Work will stop after 'max' tasks have been processed whether get_task - * returned NULL or not. If "max" is zero, all tasks will be processed. - * - * Returns: The number of tasks completed. - **/ -int run_threads(int n_threads, TPWorkFunc work, - TPGetTaskFunc get_task, TPFinalFunc final, - void *queue_args, int max, - int cpu_num, int cpu_groupsize, int cpu_offset) -{ - pthread_t *workers; - int i; - struct task_queue q; - - pthread_key_create(&status_label_key, NULL); - - workers = malloc(n_threads * sizeof(pthread_t)); - - pthread_mutex_init(&q.lock, NULL); - q.work = work; - q.get_task = get_task; - q.finalise = final; - q.queue_args = queue_args; - q.n_started = 0; - q.n_completed = 0; - q.max = max; - - /* Now it's safe to start using the status labels */ - if ( n_threads > 1 ) use_status_labels = 1; - - /* Start threads */ - for ( i=0; i<n_threads; i++ ) { - - struct worker_args *w; - - w = malloc(sizeof(struct worker_args)); - - w->tq = &q; - w->tqr = NULL; - w->id = i; - w->cpu_num = cpu_num; - w->cpu_groupsize = cpu_groupsize; - w->cpu_offset = cpu_offset; - - if ( pthread_create(&workers[i], NULL, task_worker, w) ) { - /* Not ERROR() here */ - fprintf(stderr, "Couldn't start thread %i\n", i); - n_threads = i; - break; - } - - } - - /* Join threads */ - for ( i=0; i<n_threads; i++ ) { - pthread_join(workers[i], NULL); - } - - use_status_labels = 0; - - free(workers); - - return q.n_completed; -} diff --git a/src/thread-pool.h b/src/thread-pool.h deleted file mode 100644 index a99a7ade..00000000 --- a/src/thread-pool.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * thread-pool.h - * - * A thread pool implementation - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - - -#ifndef THREAD_POOL_H -#define THREAD_POOL_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - - -#include <pthread.h> - -extern pthread_mutex_t stderr_lock; -extern signed int get_status_label(void); - - -/** - * TPGetTaskFunc: - * @qargs: The queue_args pointer which was given to run_threads(). - * Returns: A pointer which will be passed to the worker function. - * - * This function is called, non-reentrantly, to get a new work item to give to - * your work function. The stuff you need to generate the new work item should - * have been stored in @qargs which was passed to run_threads(). - * - **/ -typedef void *(*TPGetTaskFunc)(void *qargs); - - -/** - * TPWorkFunc: - * @work: The queue_args pointer which was given to run_threads(). - * @cookie: A small integral number which is guaranteed to be unique among all - * currently running threads. - * - * This function is called, reentrantly, for each work item. - * - **/ -typedef void (*TPWorkFunc)(void *work, int cookie); - - -/** - * TPFinalFunc: - * @qargs: The queue_args pointer which was given to run_threads(). - * @work: The pointer which was returned by your get_task function. - * - * This function is called, non-reentrantly, after each work item has been - * completed. A typical use might be to update some counters inside @qargs - * according to fields withing @work which were filled by your 'work' function. - * - **/ -typedef void (*TPFinalFunc)(void *qargs, void *work); - - -extern int run_threads(int n_threads, TPWorkFunc work, - TPGetTaskFunc get_task, TPFinalFunc final, - void *queue_args, int max, - int cpu_num, int cpu_groupsize, int cpu_offset); - - -#endif /* THREAD_POOL_H */ diff --git a/src/utils.c b/src/utils.c deleted file mode 100644 index 6b29627f..00000000 --- a/src/utils.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * utils.c - * - * Utility stuff - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#include <libgen.h> -#include <math.h> -#include <string.h> -#include <stdio.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <gsl/gsl_matrix.h> -#include <gsl/gsl_vector.h> -#include <gsl/gsl_blas.h> - -#include "utils.h" -#include "image.h" - - -/** - * SECTION:utils - * @short_description: Miscellaneous utilities - * @title: Utilities - * @section_id: - * @see_also: - * @include: "utils.h" - * @Image: - * - * Wibble - */ - -/** - * show_matrix_eqn: - * @M: A matrix - * @v: A vector - * @r: The number of elements in @v and the side length of @M. - * - * Displays a matrix equation of the form @M.a = @v. - * - * @M must be square. - **/ -void show_matrix_eqn(gsl_matrix *M, gsl_vector *v, int r) -{ - int i, j; - - for ( i=0; i<r; i++ ) { - STATUS("[ "); - for ( j=0; j<r; j++ ) { - STATUS("%+9.3e ", gsl_matrix_get(M, i, j)); - } - STATUS("][ a%2i ] = [ %+9.3e ]\n", i, gsl_vector_get(v, i)); - } -} - - -size_t notrail(char *s) -{ - size_t i; - size_t munched = 0; - - for ( i=strlen(s)-1; i>=0; i-- ) { - if ( (s[i] == ' ') || (s[i] == '\t') ) { - s[i] = '\0'; - munched++; - } else { - return munched; - } - } - - return munched; -} - - -void chomp(char *s) -{ - size_t i; - - if ( !s ) return; - - for ( i=0; i<strlen(s); i++ ) { - if ( (s[i] == '\n') || (s[i] == '\r') ) { - s[i] = '\0'; - return; - } - } -} - - -void progress_bar(int val, int total, const char *text) -{ - double frac; - int n, i; - char s[1024]; - const int width = 50; - - if ( total == 0 ) return; - - if ( !isatty(STDERR_FILENO) ) return; - if ( tcgetpgrp(STDERR_FILENO) != getpgrp() ) return; - - frac = (double)val/total; - n = (int)(frac*width); - - for ( i=0; i<n; i++ ) s[i] = '='; - for ( i=n; i<width; i++ ) s[i] = '.'; - s[width] = '\0'; - - pthread_mutex_lock(&stderr_lock); - fprintf(stderr, "\r%s: |%s|", text, s); - if ( val == total ) fprintf(stderr, "\n"); - pthread_mutex_unlock(&stderr_lock); - - fflush(stdout); -} - - -double random_flat(double max) -{ - return max * (double)random()/RAND_MAX; -} - - -double flat_noise(double expected, double width) -{ - double noise = random_flat(2.0*width); - return expected+noise-width; -} - - -double gaussian_noise(double expected, double stddev) -{ - double x1, x2, noise; - - /* A uniformly distributed random number between 0 and 1 */ - x1 = ((double)random()/RAND_MAX); - x2 = ((double)random()/RAND_MAX); - - noise = sqrt(-2.0*log(x1)) * cos(2.0*M_PI*x2); - - return expected + noise*stddev; -} - - -static int fake_poisson_noise(double expected) -{ - double rf = gaussian_noise(expected, sqrt(expected)); - return (int)rf; -} - - -int poisson_noise(double expected) -{ - double L; - int k = 0; - double p = 1.0; - - /* For large values of the mean, we get big problems with arithmetic. - * In such cases, fall back on a Gaussian with the right variance. */ - if ( expected > 100.0 ) return fake_poisson_noise(expected); - - L = exp(-expected); - - do { - - double r; - - k++; - r = (double)random()/(double)RAND_MAX; - p *= r; - - } while ( p > L ); - - return k - 1; -} - - -/** - * SECTION:quaternion - * @short_description: Simple quaternion handling - * @title: Quaternion - * @section_id: - * @see_also: - * @include: "utils.h" - * @Image: - * - * There is a simple quaternion structure in CrystFEL. At the moment, it is - * only used when simulating patterns, as an argument to cell_rotate() to - * orient the unit cell. - */ - -/** - * quaternion_modulus: - * @q: A %quaternion - * - * If a quaternion represents a pure rotation, its modulus should be unity. - * - * Returns: the modulus of the given quaternion. - **/ -double quaternion_modulus(struct quaternion q) -{ - return sqrt(q.w*q.w + q.x*q.x + q.y*q.y + q.z*q.z); -} - - -/** - * normalise_quaternion: - * @q: A %quaternion - * - * Rescales the quaternion such that its modulus is unity. - * - * Returns: the normalised version of @q - **/ -struct quaternion normalise_quaternion(struct quaternion q) -{ - double mod; - struct quaternion r; - - mod = quaternion_modulus(q); - - r.w = q.w / mod; - r.x = q.x / mod; - r.y = q.y / mod; - r.z = q.z / mod; - - return r; -} - - -/** - * random_quaternion: - * - * Returns: a randomly generated, normalised, quaternion. - **/ -struct quaternion random_quaternion() -{ - struct quaternion q; - - q.w = 2.0*(double)random()/RAND_MAX - 1.0; - q.x = 2.0*(double)random()/RAND_MAX - 1.0; - q.y = 2.0*(double)random()/RAND_MAX - 1.0; - q.z = 2.0*(double)random()/RAND_MAX - 1.0; - q = normalise_quaternion(q); - - return q; -} - - -/** - * quaternion_valid: - * @q: A %quaternion - * - * Checks if the given quaternion is normalised. - * - * This function performs a nasty floating point comparison of the form - * <code>(modulus > 0.999) && (modulus < 1.001)</code>, and so should not be - * relied upon to spot anything other than the most obvious input error. - * - * Returns: 1 if the quaternion is normalised, 0 if not. - **/ -int quaternion_valid(struct quaternion q) -{ - double qmod; - - qmod = quaternion_modulus(q); - - /* Modulus = 1 to within some tolerance? - * Nasty allowance for floating-point accuracy follows... */ - if ( (qmod > 0.999) && (qmod < 1.001) ) return 1; - - return 0; -} - - -/** - * quat_rot - * @q: A vector (in the form of an %rvec) - * @z: A %quaternion - * - * Rotates a vector according to a quaternion. - * - * Returns: A rotated version of @p. - **/ -struct rvec quat_rot(struct rvec q, struct quaternion z) -{ - struct rvec res; - double t01, t02, t03, t11, t12, t13, t22, t23, t33; - - t01 = z.w*z.x; - t02 = z.w*z.y; - t03 = z.w*z.z; - t11 = z.x*z.x; - t12 = z.x*z.y; - t13 = z.x*z.z; - t22 = z.y*z.y; - t23 = z.y*z.z; - t33 = z.z*z.z; - - res.u = (1.0 - 2.0 * (t22 + t33)) * q.u - + (2.0 * (t12 + t03)) * q.v - + (2.0 * (t13 - t02)) * q.w; - - res.v = (2.0 * (t12 - t03)) * q.u - + (1.0 - 2.0 * (t11 + t33)) * q.v - + (2.0 * (t01 + t23)) * q.w; - - res.w = (2.0 * (t02 + t13)) * q.u - + (2.0 * (t23 - t01)) * q.v - + (1.0 - 2.0 * (t11 + t22)) * q.w; - - return res; -} - - -/* Return non-zero if c is in delims */ -static int assplode_isdelim(const char c, const char *delims) -{ - size_t i; - for ( i=0; i<strlen(delims); i++ ) { - if ( c == delims[i] ) return 1; - } - return 0; -} - - -static int assplode_extract(char ***pbits, int n, size_t n_captured, - size_t start, const char *a) -{ - char **bits = *pbits; - bits = realloc(bits, sizeof(char *)*(n+1)); - bits[n] = malloc(n_captured+1); - memcpy(bits[n], a+start, n_captured); - bits[n][n_captured] = '\0'; - n++; - *pbits = bits; - return n; -} - - -/* Split the string 'a' using 'delims' as a zero-terminated list of - * deliminators. - * Store each segment in bits[0...n] where n is the number of segments and is - * the return value. pbits = &bits - * Each segment needs to be freed with free() when finished with. - * The array of bits also needs to be freed with free() when finished with, - * unless n=0 in which case bits==NULL - */ -int assplode(const char *a, const char *delims, char ***pbits, - AssplodeFlag flags) -{ - size_t i, start, n_captured; - int n, last_was_delim; - char **bits; - - n = 0; - i = 0; - n_captured = 0; - start = 0; - last_was_delim = 0; - bits = NULL; - while ( i < strlen(a) ) { - - if ( assplode_isdelim(a[i], delims) ) { - - if ( n_captured > 0 ) { - /* This is a deliminator after a sequence of - * non-deliminator chars */ - n = assplode_extract(&bits, n, n_captured, - start, a); - } - - n_captured = 0; - if ( (flags & ASSPLODE_DUPS) && last_was_delim ) { - n = assplode_extract(&bits, n, 0, start, a); - } - last_was_delim = 1; - - } else { - - if ( n_captured == 0 ) { - /* No characters currently found, so this is the - * start */ - start = i; - } - n_captured++; - last_was_delim = 0; - - } - - i++; - - } - /* Left over characters at the end? */ - if ( n_captured > 0 ) { - n = assplode_extract(&bits, n, n_captured, start, a); - } - - *pbits = bits; - return n; -} - - -char *check_prefix(char *prefix) -{ - int r; - struct stat statbuf; - char *new; - size_t len; - - /* Is "prefix" a directory? */ - r = stat(prefix, &statbuf); - if ( r != 0 ) { - /* "prefix" probably doesn't exist. This is fine - assume - * the user knows what they're doing, and that "prefix" - * suffixed with the actual filename will produce something - * sensible. */ - return prefix; - } - - if ( !S_ISDIR(statbuf.st_mode) ) { - /* Also fine, as above. */ - return prefix; - } - - /* Does the prefix end in a slash? */ - if ( prefix[strlen(prefix)-1] == '/' ) { - /* This looks sensible. */ - return prefix; - } - - STATUS("Your prefix ('%s') is a directory, but doesn't end" - " with a slash. I'm going to add it for you.\n", prefix); - STATUS("If this isn't what you want, run with --no-check-prefix.\n"); - len = strlen(prefix)+2; - new = malloc(len); - snprintf(new, len, "%s/", prefix); - free(prefix); - return new; -} - - -char *safe_basename(const char *in) -{ - int i; - char *cpy; - char *res; - - cpy = strdup(in); - - /* Get rid of any trailing slashes */ - for ( i=strlen(cpy)-1; i>0; i-- ) { - if ( cpy[i] == '/' ) { - cpy[i] = '\0'; - } else { - break; - } - } - - /* Find the base name */ - for ( i=strlen(cpy)-1; i>0; i-- ) { - if ( cpy[i] == '/' ) { - i++; - break; - } - } - - res = strdup(cpy+i); - /* If we didn't find a previous slash, i==0 so res==cpy */ - - free(cpy); - - return res; -} - - -#ifdef GSL_FUDGE -/* Force the linker to bring in CBLAS to make GSL happy */ -void utils_fudge_gslcblas() -{ - STATUS("%p\n", cblas_sgemm); -} -#endif diff --git a/src/utils.h b/src/utils.h deleted file mode 100644 index 1179a57f..00000000 --- a/src/utils.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * utils.h - * - * Utility stuff - * - * (c) 2006-2010 Thomas White <taw@physics.org> - * - * Part of CrystFEL - crystallography with a FEL - * - */ - -#ifndef UTILS_H -#define UTILS_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <math.h> -#include <complex.h> -#include <string.h> -#include <stdlib.h> -#include <pthread.h> -#include <gsl/gsl_matrix.h> -#include <gsl/gsl_vector.h> - - -#include "thread-pool.h" - - -/* -------------------------- Fundamental constants ------------------------ */ - -/* Electron charge in C */ -#define ELECTRON_CHARGE (1.6021773e-19) - -/* Planck's constant (Js) */ -#define PLANCK (6.62606896e-34) - -/* Speed of light in vacuo (m/s) */ -#define C_VACUO (299792458) - -/* Thomson scattering length (m) */ -#define THOMSON_LENGTH (2.81794e-15) - - -/* ------------------------------ Quaternions ------------------------------- */ - -/** - * quaternion: - * - * <programlisting> - * struct quaternion - * { - * double w - * double x - * double y - * double z - * }; - * </programlisting> - * - * A structure representing a quaternion. - * - **/ -struct quaternion; - -struct quaternion { - double w; - double x; - double y; - double z; -}; - -extern struct quaternion normalise_quaternion(struct quaternion q); -extern double quaternion_modulus(struct quaternion q); -extern struct quaternion random_quaternion(void); -extern int quaternion_valid(struct quaternion q); -extern struct rvec quat_rot(struct rvec q, struct quaternion z); - - -/* --------------------------- Useful functions ----------------------------- */ - -extern void show_matrix_eqn(gsl_matrix *M, gsl_vector *v, int r); -extern size_t notrail(char *s); -extern void chomp(char *s); - -typedef enum { - ASSPLODE_NONE = 0, - ASSPLODE_DUPS = 1<<0 -} AssplodeFlag; -extern int assplode(const char *a, const char *delims, char ***pbits, - AssplodeFlag flags); - -extern void progress_bar(int val, int total, const char *text); -extern double random_flat(double max); -extern double flat_noise(double expected, double width); -extern double gaussian_noise(double expected, double stddev); -extern int poisson_noise(double expected); - -/* Keep these ones inline, to avoid function call overhead */ -static inline struct quaternion invalid_quaternion(void) -{ - struct quaternion quat; - quat.w = 0.0; - quat.x = 0.0; - quat.y = 0.0; - quat.z = 0.0; - return quat; -} - -static inline double distance(double x1, double y1, double x2, double y2) -{ - return sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); -} - -static inline double modulus(double x, double y, double z) -{ - return sqrt(x*x + y*y + z*z); -} - -static inline double modulus_squared(double x, double y, double z) { - return x*x + y*y + z*z; -} - -static inline double distance3d(double x1, double y1, double z1, - double x2, double y2, double z2) -{ - return modulus(x1-x2, y1-y2, z1-z2); -} - -/* Answer in radians */ -static inline double angle_between(double x1, double y1, double z1, - double x2, double y2, double z2) -{ - double mod1 = modulus(x1, y1, z1); - double mod2 = modulus(x2, y2, z2); - double cosine = (x1*x2 + y1*y2 + z1*z2) / (mod1*mod2); - - /* Fix domain if outside due to rounding */ - if ( cosine > 1.0 ) cosine = 1.0; - if ( cosine < -1.0 ) cosine = -1.0; - - return acos(cosine); -} - -static inline int within_tolerance(double a, double b, double percent) -{ - double tol = fabs(a) * (percent/100.0); - if ( fabs(b-a) < tol ) return 1; - return 0; -} - - -/* ----------------------------- Useful macros ------------------------------ */ - -#define rad2deg(a) ((a)*180/M_PI) -#define deg2rad(a) ((a)*M_PI/180) - -#define is_odd(a) ((a)%2==1) - -#define biggest(a,b) ((a>b) ? (a) : (b)) -#define smallest(a,b) ((a<b) ? (a) : (b)) - - -/* Photon energy (J) to wavelength (m) */ -#define ph_en_to_lambda(a) ((PLANCK*C_VACUO)/(a)) - -/* Photon wavelength (m) to energy (J) */ -#define ph_lambda_to_en(a) ((PLANCK*C_VACUO)/(a)) - -/* eV to Joules */ -#define eV_to_J(a) ((a)*ELECTRON_CHARGE) - -/* Joules to eV */ -#define J_to_eV(a) ((a)/ELECTRON_CHARGE) - -#define UNUSED __attribute__((unused)) - -/* -------------------- Indexed lists for specified types ------------------- */ - -#include "defs.h" - -#define LIST_SIZE (IDIM*IDIM*IDIM) - -/* Create functions for storing reflection intensities indexed as h,k,l */ -#define LABEL(x) x##_intensity -#define TYPE double -#include "list_tmp.h" - -/* CAs above, but for phase values */ -#define LABEL(x) x##_phase -#define TYPE double -#include "list_tmp.h" - -/* As above, but for (unsigned) integer counts */ -#define LABEL(x) x##_count -#define TYPE unsigned int -#include "list_tmp.h" - -/* As above, but for simple flags */ -#define LABEL(x) x##_flag -#define TYPE unsigned char -#include "list_tmp.h" - - -/* ------------------------------ Message macros ---------------------------- */ - -extern pthread_mutex_t stderr_lock; - -#define ERROR(...) { \ - int error_print_val = get_status_label(); \ - pthread_mutex_lock(&stderr_lock); \ - if ( error_print_val >= 0 ) { \ - fprintf(stderr, "%3i: ", error_print_val); \ - } \ - fprintf(stderr, __VA_ARGS__); \ - pthread_mutex_unlock(&stderr_lock); \ - } - -#define STATUS(...) { \ - int status_print_val = get_status_label(); \ - pthread_mutex_lock(&stderr_lock); \ - if ( status_print_val >= 0 ) { \ - fprintf(stderr, "%3i: ", status_print_val); \ - } \ - fprintf(stderr, __VA_ARGS__); \ - pthread_mutex_unlock(&stderr_lock); \ - } - - -/* ------------------------------ File handling ----------------------------- */ - -extern char *check_prefix(char *prefix); -extern char *safe_basename(const char *in); - - -#endif /* UTILS_H */ |