diff options
-rw-r--r-- | libcrystfel/src/grainspotter.c | 242 | ||||
-rw-r--r-- | libcrystfel/src/grainspotter.h | 10 | ||||
-rw-r--r-- | libcrystfel/src/image.c | 10 | ||||
-rw-r--r-- | libcrystfel/src/image.h | 1 | ||||
-rw-r--r-- | libcrystfel/src/index.c | 37 | ||||
-rw-r--r-- | libcrystfel/src/index.h | 6 |
6 files changed, 245 insertions, 61 deletions
diff --git a/libcrystfel/src/grainspotter.c b/libcrystfel/src/grainspotter.c index 7d0f74ce..bfb61df7 100644 --- a/libcrystfel/src/grainspotter.c +++ b/libcrystfel/src/grainspotter.c @@ -54,13 +54,25 @@ #include "peaks.h" #include "cell.h" #include "cell-utils.h" +#include "grainspotter.h" #define GRAINSPOTTER_VERBOSE 0 +/* Global private data, prepared once */ +struct grainspotter_private +{ + IndexingMethod indm; + UnitCell *cell; +}; + + +/* Data needed during the run of Grainspotter */ struct grainspotter_data { + struct grainspotter_private *gp; + /* Low-level stuff */ int pty; pid_t pid; @@ -71,7 +83,8 @@ struct grainspotter_data { }; -static int read_matrix(struct image *image, char *filename) +static int read_matrix(struct grainspotter_private *gp, struct image *image, + char *filename) { FILE *fh; int d1; @@ -94,68 +107,157 @@ static int read_matrix(struct image *image, char *filename) return 1; } - /* One line per grain */ - if ( fgets(line, 1024, fh) == NULL ) { - ERROR("Failed to read GFF file.\n"); - return 1; - } + do { - STATUS("'%s'\n", line); + Crystal *cr; + UnitCell *cell; - r = sscanf(line, - "%i %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f", - &d1, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, - &ubi11, &ubi12, &ubi13, &ubi21, &ubi22, &ubi23, &ubi31, &ubi32, &ubi33); + /* One line per grain */ + if ( fgets(line, 1024, fh) == NULL ) { + ERROR("Failed to read GFF file.\n"); + return 1; + } - if ( r != 24 ) { - ERROR("Only %i parameters in GFF file\n", r); - return 1; - } + STATUS("'%s'\n", line); - fclose(fh); + r = sscanf(line, "%i %f %f %f %f %f %f %f %f %f %f %f %f" + "%f %f %f %f %f %f %f %f %f %f %f", + &d1, &d2, &d2, &d2, &d2, &d2, &d2, &d2, &d2, + &d2, &d2, &d2, &d2, &d2, &d2, + &ubi11, &ubi12, &ubi13, + &ubi21, &ubi22, &ubi23, + &ubi31, &ubi32, &ubi33); - image->candidate_cells[0] = cell_new(); + if ( r != 24 ) { + ERROR("Only %i parameters in GFF file\n", r); + return 1; + } + + cell = cell_new(); + + cell_set_cartesian(cell, ubi12/1e10, ubi13/1e10, ubi11/1e10, + ubi22/1e10, ubi23/1e10, ubi21/1e10, + ubi32/1e10, ubi33/1e10, ubi31/1e10); + + cr = crystal_new(); + if ( cr == NULL ) { + ERROR("Failed to allocate crystal.\n"); + return 0; + } -// cell_set_cartesian(image->candidate_cells[0], -// ubi11/1e10, ubi12/1e10, ubi13/1e10, -// ubi21/1e10, ubi22/1e10, ubi23/1e10, -// ubi31/1e10, ubi32/1e10, ubi33/1e10); + crystal_set_cell(cr, cell); + image_add_crystal(image, cr); - cell_set_cartesian(image->candidate_cells[0], - ubi12/1e10, ubi13/1e10, ubi11/1e10, - ubi22/1e10, ubi23/1e10, ubi21/1e10, - ubi32/1e10, ubi33/1e10, ubi31/1e10); + } while ( !feof(fh) ); + fclose(fh); - image->ncells = 1; - cell_print(image->candidate_cells[0]); + if ( gp->indm & INDEXING_CHECK_PEAKS ) { + if ( !peak_sanity_check(image, image->crystals, + image->n_crystals) ) + { + free_all_crystals(image); + return 0; + } + } return 0; } +static void gs_parseline(char *line, struct image *image, + struct grainspotter_data *gs) +{ + #if GRAINSPOTTER_VERBOSE + STATUS("%s\n", line); + #endif +} + + static int grainspotter_readable(struct image *image, - struct grainspotter_data *grainspotter) + struct grainspotter_data *gs) { int rval; + int no_string = 0; - rval = read(grainspotter->pty, - grainspotter->rbuffer, grainspotter->rbuflen); + rval = read(gs->pty, gs->rbuffer+gs->rbufpos, gs->rbuflen-gs->rbufpos); - if ( rval == -1 ) { - ERROR("Read failed: %s\n", strerror(errno)); - return 1; - } + if ( (rval == -1) || (rval == 0) ) return 1; + + gs->rbufpos += rval; + assert(gs->rbufpos <= gs->rbuflen); + + while ( (!no_string) && (gs->rbufpos > 0) ) { + + int i; + int block_ready = 0; + + /* See if there's a full line in the buffer yet */ + for ( i=0; i<gs->rbufpos-1; i++ ) { + /* Means the last value looked at is rbufpos-2 */ + + if ( (gs->rbuffer[i] == '\r') + && (gs->rbuffer[i+1] == '\n') ) { + block_ready = 1; + break; + } + + } + + if ( block_ready ) { - grainspotter->rbuffer[rval] = '\0'; + unsigned int new_rbuflen; + unsigned int endbit_length; + char *block_buffer = NULL; - printf("GrainSpotter: '%s'\n", grainspotter->rbuffer); + block_buffer = malloc(i+1); + memcpy(block_buffer, gs->rbuffer, i); + block_buffer[i] = '\0'; + + if ( block_buffer[0] == '\r' ) { + memmove(block_buffer, block_buffer+1, i); + } + + gs_parseline(block_buffer, image, gs); + free(block_buffer); + endbit_length = i+2; + + /* Now the block's been parsed, it should be + * forgotten about */ + memmove(gs->rbuffer, + gs->rbuffer + endbit_length, + gs->rbuflen - endbit_length); + + /* Subtract the number of bytes removed */ + gs->rbufpos = gs->rbufpos - endbit_length; + new_rbuflen = gs->rbuflen - endbit_length; + if ( new_rbuflen == 0 ) new_rbuflen = 256; + gs->rbuffer = realloc(gs->rbuffer, new_rbuflen); + gs->rbuflen = new_rbuflen; + + } else { + + if ( gs->rbufpos==gs->rbuflen ) { + + /* More buffer space is needed */ + gs->rbuffer = realloc(gs->rbuffer, + gs->rbuflen + 256); + gs->rbuflen = gs->rbuflen + 256; + /* The new space gets used at the next + * read, shortly... */ + + } + no_string = 1; + + } + + } return 0; } -static void write_gve(struct image *image, UnitCell *cell) +static void write_gve(struct image *image, struct grainspotter_private *gp) { FILE *fh; int i; @@ -170,7 +272,7 @@ static void write_gve(struct image *image, UnitCell *cell) return; } - cell_get_parameters(cell, &a, &b, &c, &al, &be, &ga); + cell_get_parameters(gp->cell, &a, &b, &c, &al, &be, &ga); fprintf(fh, "%.6f %.6f %.6f %.6f %.6f %.6f P\n", a*1e10, b*1e10, c*1e10, rad2deg(al), rad2deg(be), rad2deg(ga)); fprintf(fh, "# wavelength = %.6f\n", image->lambda*1e10); @@ -242,36 +344,39 @@ static char *write_ini(struct image *image) } -void run_grainspotter(struct image *image, UnitCell *cell) +int grainspotter_index(struct image *image, IndexingPrivate *ipriv) { unsigned int opts; int status; int rval; struct grainspotter_data *grainspotter; + struct grainspotter_private *gp = (struct grainspotter_private *)ipriv; char *ini_filename; char gff_filename[1024]; - write_gve(image, cell); + write_gve(image, gp); ini_filename = write_ini(image); if ( ini_filename == NULL ) { ERROR("Failed to write ini file for GrainSpotter.\n"); - return; + return 0; } grainspotter = malloc(sizeof(struct grainspotter_data)); if ( grainspotter == NULL ) { ERROR("Couldn't allocate memory for GrainSpotter data.\n"); - return; + return 0; } + grainspotter->gp = gp; + snprintf(gff_filename, 1023, "xfel-%i.gff", image->id); remove(gff_filename); grainspotter->pid = forkpty(&grainspotter->pty, NULL, NULL, NULL); if ( grainspotter->pid == -1 ) { ERROR("Failed to fork for GrainSpotter: %s\n", strerror(errno)); - return; + return 0; } if ( grainspotter->pid == 0 ) { @@ -283,8 +388,8 @@ void run_grainspotter(struct image *image, UnitCell *cell) t.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); tcsetattr(STDIN_FILENO, TCSANOW, &t); - STATUS("Running GrainSpotter.0.90 '%s'\n", ini_filename); - execlp("GrainSpotter.0.90", "", ini_filename, (char *)NULL); + STATUS("Running GrainSpotter.0.93 '%s'\n", ini_filename); + execlp("GrainSpotter.0.93", "", ini_filename, (char *)NULL); ERROR("Failed to invoke GrainSpotter.\n"); _exit(0); @@ -344,11 +449,54 @@ void run_grainspotter(struct image *image, UnitCell *cell) if ( status != 0 ) { ERROR("GrainSpotter doesn't seem to be working properly.\n"); + free(grainspotter); + return 0; } - if ( read_matrix(image, gff_filename) != 0 ) { - ERROR("Failed to read matrix\n"); + if ( read_matrix(gp, image, gff_filename) != 0 ) { + free(grainspotter); + return 0; } + /* Success! */ free(grainspotter); + return 1; +} + + + +IndexingPrivate *grainspotter_prepare(IndexingMethod *indm, UnitCell *cell, + const char *filename, + struct detector *det, + struct beam_params *beam, float *ltl) +{ + struct grainspotter_private *gp; + + if ( cell == NULL ) { + ERROR("GrainSpotter needs a unit cell.\n"); + return NULL; + } + + gp = calloc(1, sizeof(*gp)); + if ( gp == NULL ) return NULL; + + /* Flags that GrainSpotter knows about */ + *indm &= INDEXING_METHOD_MASK | INDEXING_CHECK_PEAKS; + + /* Flags that GrainSpotter requires */ + *indm |= INDEXING_USE_LATTICE_TYPE; + + gp->cell = cell; + gp->indm = *indm; + + return (IndexingPrivate *)gp; +} + + +void grainspotter_cleanup(IndexingPrivate *pp) +{ + struct grainspotter_private *p; + + p = (struct grainspotter_private *)pp; + free(p); } diff --git a/libcrystfel/src/grainspotter.h b/libcrystfel/src/grainspotter.h index 1aedf57f..720fc486 100644 --- a/libcrystfel/src/grainspotter.h +++ b/libcrystfel/src/grainspotter.h @@ -35,8 +35,16 @@ #include "cell.h" +extern IndexingPrivate *grainspotter_prepare(IndexingMethod *indm, + UnitCell *cell, + const char *filename, + struct detector *det, + struct beam_params *beam, + float *ltl); -extern void run_grainspotter(struct image *image, UnitCell *cell); +extern void grainspotter_cleanup(IndexingPrivate *pp); + +extern int grainspotter_index(struct image *image, IndexingPrivate *p); #endif /* GRAINSPOTTER_H */ diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c index 6e4fd40a..8fe3d69c 100644 --- a/libcrystfel/src/image.c +++ b/libcrystfel/src/image.c @@ -177,3 +177,13 @@ void image_add_crystal(struct image *image, Crystal *cryst) image->crystals = crs; image->n_crystals = n+1; } + + +void free_all_crystals(struct image *image) +{ + int i; + + for ( i=0; i<image->n_crystals; i++ ) { + crystal_free(image->crystals[i]); + } +} diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h index 3739c01f..0d131451 100644 --- a/libcrystfel/src/image.h +++ b/libcrystfel/src/image.h @@ -175,5 +175,6 @@ extern int image_feature_count(ImageFeatureList *flist); extern struct imagefeature *image_get_feature(ImageFeatureList *flist, int idx); extern void image_add_crystal(struct image *image, Crystal *cryst); +extern void free_all_crystals(struct image *image); #endif /* IMAGE_H */ diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 89fdec4f..eee2e814 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -51,6 +51,7 @@ #include "grainspotter.h" #include "geometry.h" #include "cell-utils.h" +#include "grainspotter.h" IndexingPrivate **prepare_indexing(IndexingMethod *indm, UnitCell *cell, @@ -68,6 +69,7 @@ IndexingPrivate **prepare_indexing(IndexingMethod *indm, UnitCell *cell, int i; IndexingMethod in; + char *str; in = indm[n]; @@ -82,16 +84,17 @@ IndexingPrivate **prepare_indexing(IndexingMethod *indm, UnitCell *cell, iprivs[n] = mosflm_prepare(&indm[n], cell, filename, det, beam, ltl); break; - - case INDEXING_GRAINSPOTTER : - iprivs[n] = indexing_private(indm[n]); - break; - case INDEXING_REAX : iprivs[n] = reax_prepare(&indm[n], cell, filename, det, beam, ltl); break; + case INDEXING_GRAINSPOTTER : + iprivs[n] = grainspotter_prepare(&indm[n], cell, + filename, det, beam, + ltl); + break; + default : ERROR("Don't know how to prepare indexing method %i\n", indm[n]); @@ -101,8 +104,9 @@ IndexingPrivate **prepare_indexing(IndexingMethod *indm, UnitCell *cell, if ( iprivs[n] == NULL ) return NULL; - STATUS("Prepared indexing method %i: %s\n", - n, indexer_str(indm[n])); + str = indexer_str(indm[n]); + STATUS("Prepared indexing method %i: %s\n", n, str); + free(str); if ( in != indm[n] ) { ERROR("Note: flags were altered to take into account " @@ -149,14 +153,14 @@ void cleanup_indexing(IndexingMethod *indms, IndexingPrivate **privs) mosflm_cleanup(privs[n]); break; - case INDEXING_GRAINSPOTTER : - free(priv[n]); - break; - case INDEXING_REAX : reax_cleanup(privs[n]); break; + case INDEXING_GRAINSPOTTER : + grainspotter_cleanup(privs[n]); + break; + default : ERROR("Don't know how to clean up indexing method %i\n", indms[n]); @@ -213,6 +217,10 @@ static int try_indexer(struct image *image, IndexingMethod indm, return reax_index(image, ipriv); break; + case INDEXING_GRAINSPOTTER : + return grainspotter_index(image, ipriv); + break; + default : ERROR("Unrecognised indexing method: %i\n", indm); break; @@ -321,8 +329,13 @@ char *indexer_str(IndexingMethod indm) strcpy(str, "reax"); break; + case INDEXING_GRAINSPOTTER : + strcpy(str, "grainspotter"); + break; + default : - ERROR("Unrecognised indexing method %i\n", indm); + ERROR("Unrecognised indexing method %i\n", + indm & INDEXING_METHOD_MASK); strcpy(str, "(unknown)"); break; diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h index a47ee9a0..3c91486b 100644 --- a/libcrystfel/src/index.h +++ b/libcrystfel/src/index.h @@ -54,6 +54,10 @@ #define INDEXING_DEFAULTS_REAX (INDEXING_REAX | INDEXING_USE_LATTICE_TYPE \ | INDEXING_CHECK_PEAKS) +#define INDEXING_DEFAULTS_GRAINSPOTTER (INDEXING_GRAINSPOTTER \ + | INDEXING_USE_LATTICE_TYPE \ + | INDEXING_CHECK_PEAKS) + /** * IndexingMethod: * @INDEXING_NONE: No indexing to be performed @@ -75,7 +79,7 @@ typedef enum { INDEXING_GRAINSPOTTER = 4, /* Bits at the top of the IndexingMethod are flags which modify the - * behaviour of the indexer, at the moment just by adding checks. */ + * behaviour of the indexer. */ INDEXING_CHECK_CELL_COMBINATIONS = 256, INDEXING_CHECK_CELL_AXES = 512, INDEXING_CHECK_PEAKS = 1024, |