aboutsummaryrefslogtreecommitdiff
path: root/src/mosflm.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2011-11-15 13:59:17 +0100
committerThomas White <taw@physics.org>2012-02-22 15:27:40 +0100
commit25c3d29ed7701cadbb3813878f25b633a7cd7c2d (patch)
tree2efd3bd84ee6948543b0bc89053f7654047b8542 /src/mosflm.c
parentfb9df2f18def2d0b8fbdbc854c8a8c10e39ce6d9 (diff)
Move indexing and rendering to libcrystfel
Diffstat (limited to 'src/mosflm.c')
-rw-r--r--src/mosflm.c609
1 files changed, 0 insertions, 609 deletions
diff --git a/src/mosflm.c b/src/mosflm.c
deleted file mode 100644
index 5df5af21..00000000
--- a/src/mosflm.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * mosflm.c
- *
- * Invoke the DPS auto-indexing algorithm through MOSFLM
- *
- * (c) 2010 Richard Kirian <rkirian@asu.edu>
- * (c) 2006-2010 Thomas White <taw@physics.org>
- *
- * Part of CrystFEL - crystallography with a FEL
- *
- */
-
-/* TODO:
- *
- * Properly read the newmat file (don't use fscanf-- spaces between numers
- * are not guaranteed)
- *
- * "Success" is indicated by existence of NEWMAT file written by mosflm.
- * Better to interact with mosflm directly in order to somehow verify success.
- *
- * Investigate how these keywords affect mosflms behavior:
- *
- * MOSAICITY
- * DISPERSION
- * DIVERGENCE
- * POLARISATION
- * POSTREF BEAM
- * POSTREF USEBEAM OFF
- * PREREFINE ON
- * EXTRA ON
- * POSTREF ON
- *
- * These did not seem to affect the results by my (Rick's) experience, probably
- * because they are only used conjunction with image intensity data, but it's
- * worth another look at the documentation.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#if HAVE_FORKPTY_LINUX
-#include <pty.h>
-#elif HAVE_FORKPTY_BSD
-#include <util.h>
-#endif
-
-
-#include "image.h"
-#include "mosflm.h"
-#include "utils.h"
-#include "peaks.h"
-
-
-#define MOSFLM_VERBOSE 0
-
-
-typedef enum {
- MOSFLM_INPUT_NONE,
- MOSFLM_INPUT_LINE,
- MOSFLM_INPUT_PROMPT
-} MOSFLMInputType;
-
-
-struct mosflm_data {
-
- /* MOSFLM auto-indexing low-level stuff */
- int pty;
- pid_t pid;
- char *rbuffer;
- int rbufpos;
- int rbuflen;
-
- /* MOSFLM high-level stuff */
- char newmatfile[128];
- char imagefile[128];
- char sptfile[128];
- int step;
- int finished_ok;
- UnitCell *target_cell;
-
-};
-
-
-static void mosflm_parseline(const char *line, struct image *image,
- struct mosflm_data *dirax)
-{
- #if MOSFLM_VERBOSE
- char *copy;
- int i;
-
- copy = strdup(line);
- for ( i=0; i<strlen(copy); i++ ) {
- if ( copy[i] == '\r' ) copy[i]='r';
- if ( copy[i] == '\n' ) copy[i]='\0';
- }
- STATUS("MOSFLM: %s\n", copy);
- free(copy);
- #endif
-}
-
-
-static int read_newmat(const char *filename, struct image *image)
-{
- FILE * fh;
- float asx, asy, asz;
- float bsx, bsy, bsz;
- float csx, csy, csz;
- int n;
- double c;
-
- fh = fopen(filename, "r");
- if ( fh == NULL ) {
- return 1;
- }
- n = fscanf(fh, "%f %f %f\n", &asx, &bsx, &csx);
- n += fscanf(fh, "%f %f %f\n", &asy, &bsy, &csy);
- n += fscanf(fh, "%f %f %f\n", &asz, &bsz, &csz);
- if ( n != 9 ) {
- STATUS("Fewer than 9 parameters found in NEWMAT file.\n");
- return 1;
- }
- fclose(fh);
-
- /* MOSFLM "A" matrix is multiplied by lambda, so fix this */
- c = 1/image->lambda;
-
- image->candidate_cells[0] = cell_new();
-
- cell_set_reciprocal(image->candidate_cells[0],
- asz*c, asy*c, asx*c,
- bsz*c, bsy*c, bsx*c,
- csz*c, csy*c, csx*c);
-
- image->ncells = 1;
-
- return 0;
-}
-
-
-/* Need to sort mosflm peaks by intensity... */
-struct sptline {
- double x; /* x coordinate of peak */
- double y; /* y coordinate of peak */
- double h; /* height of peak */
- double s; /* sigma of peak */
-};
-
-
-static int compare_vals(const void *ap, const void *bp)
-{
- const struct sptline a = *(struct sptline *)ap;
- const struct sptline b = *(struct sptline *)bp;
-
- if ( a.h < b.h ) return 1;
- if ( a.h > b.h ) return -1;
- return 0;
-}
-
-
-/* Write .spt file for mosflm */
-static void write_spt(struct image *image, const char *filename)
-{
- FILE *fh;
- int i;
- double fclen = 67.8; /* fake camera length in mm */
- double fpix = 0.075; /* fake pixel size in mm */
- double pix;
- double height = 100.0;
- double sigma = 1.0;
- int nPeaks = image_feature_count(image->features);
- struct sptline *sptlines;
-
- fh = fopen(filename, "w");
- if ( !fh ) {
- ERROR("Couldn't open temporary file '%s'\n", filename);
- return;
- }
-
- fprintf(fh, "%10d %10d %10.8f %10.6f %10.6f\n", 1, 1, fpix, 1.0, 0.0);
- fprintf(fh, "%10d %10d\n", 1, 1);
- fprintf(fh, "%10.5f %10.5f\n", 0.0, 0.0);
-
- sptlines = malloc(sizeof(struct sptline)*nPeaks);
-
- for ( i=0; i<nPeaks; i++ ) {
-
- struct imagefeature *f;
- struct panel *p;
- double xs, ys, rx, ry;
-
- f = image_get_feature(image->features, i);
- if ( f == NULL ) continue;
-
- p = find_panel(image->det, f->fs, f->ss);
- if ( p == NULL ) continue;
-
- pix = 1000.0/p->res; /* pixel size in mm */
- height = f->intensity;
-
- xs = (f->fs-p->min_fs)*p->fsx + (f->ss-p->min_ss)*p->ssx;
- ys = (f->ss-p->min_fs)*p->fsy + (f->ss-p->min_ss)*p->ssy;
- rx = xs + p->cnx;
- ry = ys + p->cny;
-
- sptlines[i].x = ry*pix*fclen/p->clen/1000.0;
- sptlines[i].y = -rx*pix*fclen/p->clen/1000.0;
- sptlines[i].h = height;
- sptlines[i].s = sigma/1000.0;
-
- }
-
- qsort(sptlines, nPeaks, sizeof(struct sptline), compare_vals);
-
- for ( i=0; i<nPeaks; i++ ) {
-
- fprintf(fh, "%10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n",
- sptlines[i].x, sptlines[i].y,
- 0.0, 0.0,
- sptlines[i].h, sptlines[i].s);
-
- }
-
- free(sptlines);
-
- fprintf(fh,"%10.2f %10.2f %10.2f %10.2f %10.2f %10.2f\n",
- -999.0,-999.0,-999.0,-999.0,-999.0,-999.0);
- fclose(fh);
-}
-
-
-/* Write a dummy 1x1 pixel image file for MOSFLM. Without post refinement,
- * MOSFLM will ignore this, but it must be present. */
-static void write_img(struct image *image, const char *filename)
-{
- FILE *fh;
- unsigned short int *intimage;
-
- intimage = malloc(sizeof(unsigned short int));
- intimage[0] = 1;
-
- fh = fopen(filename, "w");
- if ( !fh ) {
- ERROR("Couldn't open temporary file '%s'\n", filename);
- return;
- }
-
- /* Write header */
- fprintf(fh, "{\nHEADER_BYTES=512;\n");
- fprintf(fh, "BYTE_ORDER=little_endian;\n");
- fprintf(fh, "TYPE=unsigned_short;\n");
- fprintf(fh, "DIM=2;\n");
- fprintf(fh, "SIZE1=1;\n");
- fprintf(fh, "SIZE2=1;\n");
- fprintf(fh, "}\n");
-
- /* Header padding */
- while ( ftell(fh) < 512 ) fprintf(fh," ");
-
- fwrite(intimage, sizeof(unsigned short int), 1, fh);
- free(intimage);
- fclose(fh);
-}
-
-
-static void mosflm_sendline(const char *line, struct mosflm_data *mosflm)
-{
- #if MOSFLM_VERBOSE
- char *copy;
- int i;
-
- copy = strdup(line);
- for ( i=0; i<strlen(copy); i++ ) {
- if ( copy[i] == '\r' ) copy[i]='\0';
- if ( copy[i] == '\n' ) copy[i]='\0';
- }
- STATUS("To MOSFLM: '%s'\n", copy);
- free(copy);
- #endif
-
- write(mosflm->pty, line, strlen(line));
-}
-
-
-static void mosflm_send_next(struct image *image, struct mosflm_data *mosflm)
-{
- char tmp[256];
- char symm[32];
- const char *sg;
- double wavelength;
- double a, b, c, alpha, beta, gamma;
- int i, j;
-
- switch ( mosflm->step ) {
-
- case 1 :
- mosflm_sendline("DETECTOR ROTATION HORIZONTAL"
- " ANTICLOCKWISE ORIGIN LL FAST HORIZONTAL"
- " RECTANGULAR\n", mosflm);
- break;
-
- case 2 :
- if ( mosflm->target_cell != NULL ) {
- cell_get_parameters(mosflm->target_cell, &a, &b, &c,
- &alpha, &beta, &gamma);
- snprintf(tmp, 255,
- "CELL %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f\n",
- a*1e10, b*1e10, c*1e10,
- rad2deg(alpha), rad2deg(beta), rad2deg(gamma));
- mosflm_sendline(tmp, mosflm);
- } else {
- mosflm_sendline("# Do nothing\n", mosflm);
- }
- break;
-
- case 3 :
- if ( mosflm->target_cell != NULL ) {
- sg = cell_get_spacegroup(mosflm->target_cell);
- /* Remove white space from space group */
- j = 0;
- for ( i=0; i<strlen(sg); i++ ) {
- if (sg[i] != ' ') {
- symm[j++] = sg[i];
- }
- }
- symm[j] = '\0';
- snprintf(tmp, 255, "SYMM %s\n", symm);
- mosflm_sendline(tmp, mosflm);
- } else {
- mosflm_sendline("SYMM P1\n", mosflm);
- }
- break;
-
- case 4 :
- mosflm_sendline("DISTANCE 67.8\n", mosflm);
- break;
-
- case 5 :
- mosflm_sendline("BEAM 0.0 0.0\n", mosflm);
- break;
-
- case 6 :
- wavelength = image->lambda*1e10;
- snprintf(tmp, 255, "WAVELENGTH %10.5f\n", wavelength);
- mosflm_sendline(tmp, mosflm);
- break;
-
- case 7 :
- snprintf(tmp, 255, "NEWMAT %s\n", mosflm->newmatfile);
- mosflm_sendline(tmp, mosflm);
- break;
-
- case 8 :
- snprintf(tmp, 255, "IMAGE %s phi 0 0\n", mosflm->imagefile);
- mosflm_sendline(tmp, mosflm);
- break;
-
- case 9 :
- snprintf(tmp, 255, "AUTOINDEX DPS FILE %s"
- " IMAGE 1 MAXCELL 1000 REFINE\n",
- mosflm->sptfile);
-
- /* "This option is only available if you e-mail Andrew Leslie
- * and ask for it." - MOSFLM
- * snprintf(tmp, 255, "AUTOINDEX NODISPLAY IMAGE 1 FILE %s\n",
- * mosflm->sptfile); */
- mosflm_sendline(tmp, mosflm);
- break;
-
- case 10 :
- mosflm_sendline("GO\n", mosflm);
- mosflm->finished_ok = 1;
- break;
-
- default:
- mosflm_sendline("exit\n", mosflm);
- return;
-
- }
-
- mosflm->step++;
-}
-
-
-static int mosflm_readable(struct image *image, struct mosflm_data *mosflm)
-{
- int rval;
- int no_string = 0;
-
- rval = read(mosflm->pty, mosflm->rbuffer+mosflm->rbufpos,
- mosflm->rbuflen-mosflm->rbufpos);
-
- if ( (rval == -1) || (rval == 0) ) return 1;
-
- mosflm->rbufpos += rval;
- assert(mosflm->rbufpos <= mosflm->rbuflen);
-
- while ( (!no_string) && (mosflm->rbufpos > 0) ) {
-
- int i;
- int block_ready = 0;
- MOSFLMInputType type = MOSFLM_INPUT_NONE;
-
- /* See if there's a full line in the buffer yet */
- for ( i=0; i<mosflm->rbufpos-1; i++ ) {
- /* Means the last value looked at is rbufpos-2 */
-
- /* Is there a prompt in the buffer? */
- if ( (i+10 <= mosflm->rbufpos)
- && (!strncmp(mosflm->rbuffer+i, "MOSFLM => ", 10)) ) {
- block_ready = 1;
- type = MOSFLM_INPUT_PROMPT;
- break;
- }
-
- if ( (mosflm->rbuffer[i] == '\r')
- && (mosflm->rbuffer[i+1] == '\n') ) {
- block_ready = 1;
- type = MOSFLM_INPUT_LINE;
- break;
- }
-
- }
-
- if ( block_ready ) {
-
- unsigned int new_rbuflen;
- unsigned int endbit_length;
- char *block_buffer = NULL;
-
- switch ( type ) {
-
- case MOSFLM_INPUT_LINE :
-
- block_buffer = malloc(i+1);
- memcpy(block_buffer, mosflm->rbuffer, i);
- block_buffer[i] = '\0';
-
- if ( block_buffer[0] == '\r' ) {
- memmove(block_buffer, block_buffer+1, i);
- }
-
- mosflm_parseline(block_buffer, image, mosflm);
- free(block_buffer);
- endbit_length = i+2;
- break;
-
- case MOSFLM_INPUT_PROMPT :
-
- mosflm_send_next(image, mosflm);
- endbit_length = i+7;
- break;
-
- default :
-
- /* Obviously, this never happens :) */
- ERROR("Unrecognised MOSFLM input mode! "
- "I don't know how to understand MOSFLM\n");
- return 1;
-
- }
-
- /* Now the block's been parsed, it should be
- * forgotten about */
- memmove(mosflm->rbuffer,
- mosflm->rbuffer + endbit_length,
- mosflm->rbuflen - endbit_length);
-
- /* Subtract the number of bytes removed */
- mosflm->rbufpos = mosflm->rbufpos
- - endbit_length;
- new_rbuflen = mosflm->rbuflen - endbit_length;
- if ( new_rbuflen == 0 ) new_rbuflen = 256;
- mosflm->rbuffer = realloc(mosflm->rbuffer,
- new_rbuflen);
- mosflm->rbuflen = new_rbuflen;
-
- } else {
-
- if ( mosflm->rbufpos==mosflm->rbuflen ) {
-
- /* More buffer space is needed */
- mosflm->rbuffer = realloc(
- mosflm->rbuffer,
- mosflm->rbuflen + 256);
- mosflm->rbuflen = mosflm->rbuflen + 256;
- /* The new space gets used at the next
- * read, shortly... */
-
- }
- no_string = 1;
-
- }
-
- }
-
- return 0;
-}
-
-
-void run_mosflm(struct image *image, UnitCell *cell)
-{
- struct mosflm_data *mosflm;
- unsigned int opts;
- int status;
- int rval;
-
- mosflm = malloc(sizeof(struct mosflm_data));
- if ( mosflm == NULL ) {
- ERROR("Couldn't allocate memory for MOSFLM data.\n");
- return;
- }
-
- mosflm->target_cell = cell;
-
- snprintf(mosflm->imagefile, 127, "xfel-%i_001.img", image->id);
- write_img(image, mosflm->imagefile); /* Dummy image */
-
- snprintf(mosflm->sptfile, 127, "xfel-%i_001.spt", image->id);
- write_spt(image, mosflm->sptfile);
-
- snprintf(mosflm->newmatfile, 127, "xfel-%i.newmat", image->id);
- remove(mosflm->newmatfile);
-
- mosflm->pid = forkpty(&mosflm->pty, NULL, NULL, NULL);
- if ( mosflm->pid == -1 ) {
- ERROR("Failed to fork for MOSFLM\n");
- free(mosflm);
- return;
- }
- if ( mosflm->pid == 0 ) {
-
- /* Child process: invoke MOSFLM */
- struct termios t;
-
- /* Turn echo off */
- tcgetattr(STDIN_FILENO, &t);
- t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
- tcsetattr(STDIN_FILENO, TCSANOW, &t);
-
- execlp("ipmosflm", "", (char *)NULL);
- ERROR("Failed to invoke MOSFLM.\n");
- _exit(0);
-
- }
-
- mosflm->rbuffer = malloc(256);
- mosflm->rbuflen = 256;
- mosflm->rbufpos = 0;
-
- /* Set non-blocking */
- opts = fcntl(mosflm->pty, F_GETFL);
- fcntl(mosflm->pty, F_SETFL, opts | O_NONBLOCK);
-
- mosflm->step = 1; /* This starts the "initialisation" procedure */
- mosflm->finished_ok = 0;
-
- do {
-
- fd_set fds;
- struct timeval tv;
- int sval;
-
- FD_ZERO(&fds);
- FD_SET(mosflm->pty, &fds);
-
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- sval = select(mosflm->pty+1, &fds, NULL, NULL, &tv);
-
- if ( sval == -1 ) {
- int err = errno;
- ERROR("select() failed: %s\n", strerror(err));
- rval = 1;
- } else if ( sval != 0 ) {
- rval = mosflm_readable(image, mosflm);
- } else {
- ERROR("No response from MOSFLM..\n");
- rval = 1;
- }
-
- } while ( !rval );
-
- close(mosflm->pty);
- free(mosflm->rbuffer);
- waitpid(mosflm->pid, &status, 0);
-
- if ( mosflm->finished_ok == 0 ) {
- ERROR("MOSFLM doesn't seem to be working properly.\n");
- } else {
- /* Read the mosflm NEWMAT file and get cell if found */
- read_newmat(mosflm->newmatfile, image);
- }
-
- free(mosflm);
-}