diff options
Diffstat (limited to 'libcrystfel/src/indexers')
-rw-r--r-- | libcrystfel/src/indexers/fromfile.c | 436 |
1 files changed, 198 insertions, 238 deletions
diff --git a/libcrystfel/src/indexers/fromfile.c b/libcrystfel/src/indexers/fromfile.c index 400683ae..aa2c8999 100644 --- a/libcrystfel/src/indexers/fromfile.c +++ b/libcrystfel/src/indexers/fromfile.c @@ -38,336 +38,296 @@ /** \file fromfile.h */ -/* There are 9 vector components, - * 2 detector shifts, 1 profile radius, - * 1 resolution limit */ -#define NPARAMS_PER_LINE 11 -/* The keys read from file - * are the filename, event */ -#define NKEYS_PER_LINE 2 - - struct fromfile_options { char *filename; }; +#define MAX_KEY_LEN (256) +#define MAX_CRYSTALS (16) -struct fromfile_keys +struct fromfile_key { - char filename[100]; - char event[100]; - int crystal_number; + char filename[MAX_KEY_LEN]; + char event[MAX_KEY_LEN]; }; -struct fromfile_entries +struct fromfile_entry { - struct fromfile_keys key; - float solution[NPARAMS_PER_LINE]; + struct fromfile_key key_field; + Crystal *crystals[MAX_CRYSTALS]; + int n_crystals; UT_hash_handle hh; }; struct fromfile_private { - UnitCell *cellTemplate; - struct fromfile_entries *sol_hash; + struct fromfile_entry *sol_hash; }; -void print_struct(struct fromfile_entries *sol_hash) +static int make_key(struct fromfile_key *key, + const char *filename, const char *ev) { - struct fromfile_entries *s; + if ( (strlen(filename) > MAX_KEY_LEN) || (strlen(ev) > MAX_KEY_LEN) ) { + ERROR("Filename/event too long: %s %s\n", filename, ev); + return 1; + } - s = calloc(1, sizeof(struct fromfile_entries)); - if ( s == NULL ) return; + /* The entire structure is used as a key, not just the pre-terminator + * parts of the strings. Therefore it must be initialised to zero */ + memset(key, 0, sizeof(struct fromfile_key)); - for( s=sol_hash; s != NULL; s=s->hh.next ) { - printf("File %s, event %s, and crystal_number %d \n", - s->key.filename, s->key.event, s->key.crystal_number); - } + strcpy(key->filename, filename); + strcpy(key->event, ev); + + return 0; } -void full_print_struct(struct fromfile_entries *sol_hash) +struct fromfile_entry *add_unique(struct fromfile_entry **phead, + struct fromfile_key key) { - struct fromfile_entries *s; - s = calloc(1, sizeof(struct fromfile_entries)); - if ( s == NULL ) return; - - for( s=sol_hash; s != NULL; s=s->hh.next ) { - printf("File %s, event %s, and crystal_number %d \n", - s->key.filename, s->key.event, - s->key.crystal_number); - - printf("Solution parameters:\n"); - for( int i = 0; i < NPARAMS_PER_LINE; i++ ){ - printf("%e", s->solution[i]); - } - printf("\n"); + struct fromfile_entry *p; + struct fromfile_entry *head = *phead; + + HASH_FIND(hh, head, &key, sizeof(struct fromfile_key), p); + if ( p == NULL ) { + + struct fromfile_entry *item; + + item = malloc(sizeof(struct fromfile_entry)); + if ( item == NULL ) return NULL; + + item->n_crystals = 0; + item->key_field = key; + + HASH_ADD(hh, head, key_field, sizeof(struct fromfile_key), item); + *phead = head; + return item; + + } else { + return p; } } -int ncrystals_in_sol(char *path) +static int set_ua(UnitCell *cell, const char *ltsym) { - FILE *fh; - int count = 0; /* Line counter (result) */ - char c; /* To store a character read from file */ + if ( strlen(ltsym) != 3 ) return 1; + cell_set_unique_axis(cell, ltsym[2]); + return 0; +} - fh = fopen(path, "r"); - if ( fh == NULL ) { - ERROR("%s not found by ncrystals_in_sol\n", path); - return 0; - } +static int set_lattice(UnitCell *cell, const char *ltsym) +{ + if ( (strlen(ltsym) != 2) && (strlen(ltsym) != 3) ) return 1; + + switch ( ltsym[1] ) { + case 'P': + case 'A': + case 'B': + case 'C': + case 'I': + case 'F': + case 'R': + case 'H': + break; - for ( c = getc(fh); c != EOF; c = getc(fh) ) { - if ( c == '\n' ) { - count = count + 1; - } + default: + return 1; } + cell_set_centering(cell, ltsym[1]); - /* For the last line, which has no \n at the end*/ - count = count + 1; + switch ( ltsym[0] ) { - fclose(fh); + case 'a' : + cell_set_lattice_type(cell, L_TRICLINIC); + break; - return count; -} + case 'm' : + cell_set_lattice_type(cell, L_MONOCLINIC); + return set_ua(cell, ltsym); + case 'o' : + cell_set_lattice_type(cell, L_ORTHORHOMBIC); + break; -char *read_unknown_string(FILE *fh) -{ - /* Source: "https://stackoverflow.com/questions/16870485/ - * how-can-i-read-an-input-string-of-unknown-length" */ + case 't' : + cell_set_lattice_type(cell, L_TETRAGONAL); + return set_ua(cell, ltsym); - char *str = NULL; - int ch; - size_t len = 0; - size_t size = 1; + case 'c' : + cell_set_lattice_type(cell, L_CUBIC); + break; - str = realloc(NULL, sizeof(char)*size); //size is start size - if ( !str ) { - ERROR("Can't reallocate string size"); - } + case 'r' : + cell_set_lattice_type(cell, L_RHOMBOHEDRAL); + break; - while( ( ch = fgetc(fh) ) != ' ' && ch != EOF ){ - if (ch != '\n'){ - str[len++]=ch; - } - if(len==size){ - size+=64; - str = realloc(str, sizeof(char)*(size)); - if ( !str ) { - ERROR("Can't reallocate string size"); - } - } + case 'h' : + cell_set_lattice_type(cell, L_HEXAGONAL); + return set_ua(cell, ltsym); + + default : + return 1; } - return realloc(str, sizeof(char)*len); + return 0; } void *fromfile_prepare(IndexingMethod *indm, struct fromfile_options *opts) { FILE *fh; - int nlines; - int nparams_in_solution; - int nentries; - char *filename; - char *event; - int crystal_number; - int current_line; - int position_in_current_line; - struct fromfile_entries *sol_hash = NULL; - struct fromfile_entries *item = NULL; - float params[NPARAMS_PER_LINE]; + struct fromfile_private *dp; - fh = fopen(opts->filename, "r"); - if ( fh == NULL ) { - ERROR("%s not found by fromfile_prepare\n", opts->filename); + if ( opts->filename == NULL ) { + ERROR("Please try again with --fromfile-input-file\n"); return NULL; - } else { - STATUS("Found solution file %s\n", opts->filename); } - nlines = ncrystals_in_sol(opts->filename); - /* Total crystal parameters in solution file */ - nparams_in_solution = nlines*NPARAMS_PER_LINE; - /* Total entries in solution file */ - nentries = nlines*(NPARAMS_PER_LINE+NKEYS_PER_LINE); - - STATUS("Parsing solution file containing %d lines...\n", nlines); - - /* Reads indexing solutions */ - int j = 0; /* follows the solution parameter [0,NPARAMS_PER_LINE] */ - for(int i = 0; i < nentries; i++) { - - crystal_number = 0; - - current_line = i/(NPARAMS_PER_LINE+NKEYS_PER_LINE); - - position_in_current_line = (i)%(NPARAMS_PER_LINE+NKEYS_PER_LINE); - - if ( position_in_current_line == 0 ) { + dp = malloc(sizeof(struct fromfile_private)); + if ( dp == NULL ) return NULL; - filename = read_unknown_string(fh); - - if ( !filename ){ - if ( current_line == nlines-1 ) break; - printf("Failed to read a filename\n"); - return 0; - } + fh = fopen(opts->filename, "r"); + if ( fh == NULL ) { + ERROR("Couldn't find solution file '%s'\n", opts->filename); + return NULL; + } + dp->sol_hash = NULL; + + /* Read indexing solutions */ + do { + + char *rval; + char line[1024]; + int i, n; + char **bits; + float vals[11]; + struct fromfile_key key; + Crystal *cr; + UnitCell *cell; + struct fromfile_entry *item = NULL; + + rval = fgets(line, 1023, fh); + if ( rval == NULL ) break; + + /* FIXME: Replace this with something that can handle quoted + * filenames with possible spaces */ + chomp(line); + notrail(line); + n = assplode(line, " \t,", &bits, ASSPLODE_NONE); + if ( n < 14 ) { + ERROR("Badly formatted line '%s'\n", line); + return NULL; } - if ( position_in_current_line == 1 ) { - event = read_unknown_string(fh); - if ( !event ){ - printf("Failed to read a event\n"); - return 0; + /* filename, event, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz, + * det_shift_x, det_shift_y, latticetype+centering */ + for ( i=2; i<13; i++ ) { + if (sscanf(bits[i], "%f", &vals[i-2]) != 1) + { + ERROR("Invalid value for number %i\n", i); + return NULL; } + } + if ( make_key(&key, bits[0], bits[1]) ) { + ERROR("Failed to make key for %s %s\n", + bits[0], bits[1]); + continue; } - if ( position_in_current_line > 1 ) { - if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { - printf("Failed to read a parameter\n"); - return 0; - } - j+=1; + item = add_unique(&dp->sol_hash, key); + if ( item == NULL ) { + ERROR("Failed to add/find entry for %s %s\n", + bits[0], bits[1]); + continue; } - if ( j == (NPARAMS_PER_LINE) ) { + if ( item->n_crystals == MAX_CRYSTALS ) { - /* Prepare to add to the hash table */ - item = (struct fromfile_entries *)malloc(sizeof *item); - memset(item, 0, sizeof *item); - strcpy(item->key.filename, filename); - strcpy(item->key.event, event); - item->key.crystal_number = crystal_number; - for ( int k = 0; k < NPARAMS_PER_LINE; k++){ - item->solution[k] = params[k]; - } + ERROR("Too many crystals for %s %s\n", bits[0], bits[1]); - /* Verify the uniqueness of the key */ - struct fromfile_entries *uniqueness_test; - HASH_FIND(hh, sol_hash, &item->key, - sizeof(struct fromfile_keys), uniqueness_test); + } else { - if ( uniqueness_test == NULL ) { - HASH_ADD(hh, sol_hash, key, - sizeof(struct fromfile_keys), item); + cr = crystal_new(); + + /* mm -> m */ + crystal_set_det_shift(cr, vals[9]*1e-3, vals[10]*1e-3); + + cell = cell_new(); + cell_set_reciprocal(cell, vals[0]*1e9, vals[1]*1e9, vals[2]*1e9, + vals[3]*1e9, vals[4]*1e9, vals[5]*1e9, + vals[6]*1e9, vals[7]*1e9, vals[8]*1e9); + if ( set_lattice(cell, bits[13]) ) { + ERROR("Invalid lattice type '%s'\n", bits[13]); } else { - /* Look for the next available set of keys */ - do { - uniqueness_test = NULL; - crystal_number += 1; - item->key.crystal_number = crystal_number; - HASH_FIND(hh, sol_hash, &item->key, - sizeof(struct fromfile_keys), - uniqueness_test); - } while ( uniqueness_test != NULL ); - - HASH_ADD(hh, sol_hash, key, - sizeof(struct fromfile_keys), item); + crystal_set_cell(cr, cell); + item->crystals[item->n_crystals++] = cr; } - j=0; - } - } - fclose(fh); + for ( i=0; i<n; i++ ) free(bits[i]); + free(bits); - STATUS("Solution parsing done. Have %d parameters and %d total entries.\n", - nparams_in_solution, nentries); - - struct fromfile_private *dp; - dp = (struct fromfile_private *) malloc( sizeof(struct fromfile_private)); - - if ( dp == NULL ){ - return NULL; - } + } while ( 1 ); - dp->cellTemplate = cell; - dp->sol_hash = sol_hash; + fclose(fh); - STATUS("Solution lookup table initialized!\n"); + STATUS("Read %i crystals from %s\n", + HASH_CNT(hh, dp->sol_hash), opts->filename); - return (void *)dp; + return dp; } -int fromfile_index(struct image *image, void *mpriv, int crystal_number) +int fromfile_index(struct image *image, void *mpriv) { - Crystal *cr; - UnitCell *cell; - float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz; - float xshift, yshift; - struct fromfile_entries *item, *p, *pprime; - int ncryst = 0; - float *sol; + struct fromfile_entry *p; struct fromfile_private *dp = mpriv; + struct fromfile_key key; + int i; + + make_key(&key, image->filename, image->ev); - /* Look up the hash table */ - item = calloc(1, sizeof(struct fromfile_entries)); - strcpy(item->key.filename, image->filename); - strcpy(item->key.event, image->ev); - item->key.crystal_number = crystal_number; - - /* key already in the hash? */ - HASH_FIND(hh, dp->sol_hash, &item->key, sizeof(struct fromfile_keys), p); - if ( p == NULL ) return 0; - - sol = &(p->solution)[0]; - - asx = sol[0] * 1e9; - asy = sol[1] * 1e9; - asz = sol[2] * 1e9; - bsx = sol[3] * 1e9; - bsy = sol[4] * 1e9; - bsz = sol[5] * 1e9; - csx = sol[6] * 1e9; - csy = sol[7] * 1e9; - csz = sol[8] * 1e9; - xshift = sol[9] * 1e-3; - yshift = sol[10] * 1e-3; - - cell = cell_new(); - cell_set_reciprocal(cell, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); - cell_set_lattice_type(cell, cell_get_lattice_type(dp->cellTemplate)); - cell_set_centering(cell, cell_get_centering(dp->cellTemplate)); - cell_set_unique_axis(cell, cell_get_unique_axis(dp->cellTemplate)); - - cr = crystal_new(); - ncryst += 1; - crystal_set_cell(cr, cell); - crystal_set_det_shift(cr, xshift , yshift); - image_add_crystal(image, cr); - - /* Look for additional crystals */ - item->key.crystal_number = crystal_number+1; - HASH_FIND(hh, dp->sol_hash, &item->key, - sizeof(struct fromfile_keys), pprime); - - /* If a similar tag exist, - * recursive call increasing the crystal_number by 1 */ - if ( pprime != NULL ) { - ncryst += fromfile_index(image, mpriv, crystal_number+1); + HASH_FIND(hh, dp->sol_hash, &key, sizeof(struct fromfile_key), p); + if ( p == NULL ) { + STATUS("WARNING: No solution for %s %s\n", + image->filename, image->ev); + return 0; } - return ncryst; + for ( i=0; i<p->n_crystals; i++ ) { + Crystal *cr; + cr = crystal_copy_deep(p->crystals[i]); + image_add_crystal(image, cr); + } + + return p->n_crystals; } void fromfile_cleanup(void *mpriv) { struct fromfile_private *dp = mpriv; - - /* FIXME: Implementation */ + struct fromfile_entry *item, *tmp; + + HASH_ITER(hh, dp->sol_hash, item, tmp) { + int i; + HASH_DEL(dp->sol_hash, item); + for ( i=0; i<item->n_crystals; i++ ) { + Crystal *cr = item->crystals[i]; + cell_free(crystal_get_cell(cr)); + crystal_free(cr); + } + } free(dp); } |