From f1a24d0e4c32735fa016cbb262b61a1cce5960fc Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Thu, 9 Jul 2020 14:38:19 +0200 Subject: unit cell vectors are correct, space group missing --- libcrystfel/src/index.c | 288 ++++++++++-- libcrystfel/src/index.h | 5 +- libcrystfel/src/uthash.h | 1150 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1413 insertions(+), 30 deletions(-) create mode 100755 libcrystfel/src/uthash.h (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index dc689df2..ab451c41 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -60,9 +60,31 @@ #include "xgandalf.h" #include "pinkindexer.h" +#include "uthash.h" + /** \file index.h */ +struct skip_private +{ + char path_to_sol[50]; + float solutions[]; +}; + +struct record_key_t{ //added + char filename[100]; + char event_path[35]; + int event_dim; +}; + +struct record_t{ //added + struct record_key_t key; + int line; + UT_hash_handle hh; +}; + +//declared as global variable +struct record_t *line_hash = NULL; //added struct _indexingprivate { @@ -75,6 +97,24 @@ struct _indexingprivate void **engine_private; }; +void delete_all() { + struct record_t *current_line, *tmp; + + HASH_ITER(hh, line_hash, current_line, tmp) { + HASH_DEL(line_hash, current_line); + free(current_line); + } +} + +void print_struct() { + struct record_t *s; + s = (struct record_t *)malloc(sizeof *s); + memset(s, 0, sizeof *s); + + for(s=line_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { + printf("The line is event_path %s and event_dim %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.filename); + } +} static const char *onoff(int a) { @@ -113,37 +153,225 @@ static void show_indexing_flags(IndexingFlags flags) } -static int debug_index(struct image *image) -{ +void *skip_prepare(char *solution_filename) +{ FILE *fh; - Crystal *cr; - UnitCell *cell; - float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz; + int nlines; + int nparams_in_solution; + int nparams_per_line; + int nparams; + char *filename[35]; //??? is that correct + char *event_path[35]; //??? is that correct + int event_dim; + int current_line; + int position_in_current_line; + struct record_t *item; + + //Assembling solution file name from input file name to crystfel + char path_to_sol[50],extension[10]; + strcpy(path_to_sol,"../"); + strcpy(extension,".sol"); + strtok(solution_filename, "."); //Takes the first part of the list name (before the .) + strcat(path_to_sol, strtok(solution_filename, ".") ); //Add .sol at the previously splitted name + strcat(path_to_sol, extension ); + + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) != NULL) { + //printf("Path where skip_prepare is ran: %s\n", cwd); + } + + fh = fopen(path_to_sol, "r"); - fh = fopen("../../indexing.debug", "r"); if ( fh == NULL ) { - ERROR("indexing.debug not found\n"); + ERROR("indexing.sol not found by skip_prepare\n"); return 0; } - if ( fscanf(fh, "%e %e %e", &asx, &asy, &asz) != 3 ) { - ERROR("Failed to read a* from indexing.debug\n"); - return 0; + nlines = ncrystals_in_sol(path_to_sol); + nparams_per_line = 11; //There are 9 vector component and 2 detector shifts excluding filename and event + nparams_in_solution = nlines*nparams_per_line; + nparams = nlines*(nparams_per_line+3); + + float *params = malloc(nparams_in_solution * sizeof( float)); + + //Reads indexing solutions + int j = 0; //index that follows the solution parameter + for(int i = 0; i < nparams; i++) + { + + current_line = i/(nparams_per_line+3); + + position_in_current_line = (i)%(nparams_per_line+3); + + if (position_in_current_line == 0){ + + if ( fscanf(fh, "%s", filename) != 1 ) { + if (current_line == (nlines-1)){ + break; + } + else{ + printf("Failed to read a filename from indexing.sol with skip_prepare\n"); + return 0; + } + } + } + + if (position_in_current_line == 1){ + + if ( fscanf(fh, "%s", event_path) != 1 ) { + printf("Failed to read an event_path from indexing.sol with skip_prepare\n"); + return 0; + } + } + + if (position_in_current_line == 2){ + if ( fscanf(fh, "%d", &event_dim) != 1 ) { + printf("Failed to read an event from indexing.sol with skip_prepare\n"); + return 0; + } + + //Prepare to add to the hash table once an event is read + item = (struct record_t *)malloc(sizeof *item); + memset(item, 0, sizeof *item); + strcpy(item->key.filename, filename); + strcpy(item->key.event_path, event_path); + item->key.event_dim = event_dim; + item->line=current_line; + + //Verify the uniqueness of the key + struct record_t *uniqueness_test; + HASH_FIND(hh, line_hash, &item->key, sizeof(struct record_key_t), uniqueness_test); /* id already in the hash? */ + if (uniqueness_test==NULL) { + //If not in the table, add + HASH_ADD(hh, line_hash, key, sizeof(struct record_key_t), item); + } + else{ + //If already in the table, break with error + printf("Keys to the data must be unique! Verify the combination filename, event_path, event_dim"); + return 0; + } + + + + } + + if (position_in_current_line > 2){ + if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { + printf("Failed to read a parameter from indexing.sol with skip_prepare\n"); + return 0; + } + j+=1; + } + } + + fclose(fh); + + struct skip_private *dp; + dp = (struct skip_private *) malloc( sizeof(struct skip_private) + nparams * sizeof( float) ); + + if ( dp == NULL ) return NULL; + + memcpy(dp->path_to_sol, path_to_sol, sizeof path_to_sol); + + for (int k = 0; k < nparams; k++) + { + dp->solutions[k] = params[k]; } - if ( fscanf(fh, "%e %e %e", &bsx, &bsy, &bsz) != 3 ) { - ERROR("Failed to read b* from indexing.debug\n"); + + free(params); + + return (void *)dp; +} + +int ncrystals_in_sol(char *path) +{ + FILE *fh; + int count = 0; // Line counter (result) + char c; // To store a character read from file + + fh = fopen(path, "r"); + + if ( fh == NULL ) { + ERROR("%s not found by ncrystals_in_sol\n",path); return 0; } - if ( fscanf(fh, "%e %e %e", &csx, &csy, &csz) != 3 ) { - ERROR("Failed to read c* from indexing.debug\n"); + + for (c = getc(fh); c != EOF; c = getc(fh)) + if (c == '\n') // Increment count if this character is newline + count = count + 1; + + //For the last line, which has no \n at the end + count = count + 1; + + // Close the file + fclose(fh); + + return count; + +} + +//Fonction from pinkindexer.c to update the detector center of individual crystals +//hack for electron crystallography while crystal_set_det_shift is not working approprietly +static void update_detector(struct detector *det, double xoffs, double yoffs) +{ + int i; + + for (i = 0; i < det->n_panels; i++) { + struct panel *p = &det->panels[i]; + p->cnx += xoffs * p->res; + p->cny += yoffs * p->res; + } +} + +static int skip_index(struct image *image, void *mpriv) +{ + Crystal *cr; + UnitCell *cell; + float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz, xshift, yshift; + int serial; + int nparams_per_line; + struct record_t *item, *p; + int line_number; + + struct skip_private *dp = (struct skip_private *)mpriv; + + //Look up the hash table + item = (struct record_t *)malloc(sizeof *item); + memset(item, 0, sizeof *item); + strcpy(item->key.filename, image->filename); + strcpy(item->key.event_path, *image->event->path_entries); + item->key.event_dim = *image->event->dim_entries; + + HASH_FIND(hh, line_hash, &item->key, sizeof(struct record_key_t), p); /* id already in the hash? */ + if (p==NULL) { + printf("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); return 0; } + line_number = p->line; + nparams_per_line = 11; + + asx = dp->solutions[(line_number * nparams_per_line) + 0]; + asy = dp->solutions[(line_number * nparams_per_line) + 1]; + asz = dp->solutions[(line_number * nparams_per_line) + 2]; + bsx = dp->solutions[(line_number * nparams_per_line) + 3]; + bsy = dp->solutions[(line_number * nparams_per_line) + 4]; + bsz = dp->solutions[(line_number * nparams_per_line) + 5]; + csx = dp->solutions[(line_number * nparams_per_line) + 6]; + csy = dp->solutions[(line_number * nparams_per_line) + 7]; + csz = dp->solutions[(line_number * nparams_per_line) + 8]; + xshift = dp->solutions[(line_number * nparams_per_line) + 9]; + yshift = dp->solutions[(line_number * nparams_per_line) + 10]; + cr = crystal_new(); cell = cell_new(); - cell_set_reciprocal(cell, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); + cell_set_reciprocal(cell, asx * 1e9, asy * 1e9, asz* 1e9, bsx * 1e9, bsy * 1e9, bsz * 1e9, csx * 1e9, csy * 1e9, csz* 1e9); + crystal_set_cell(cr, cell); + crystal_set_det_shift(cr, xshift * 1e-3, yshift * 1e-3); + update_detector(image->det, xshift * 1e-3, yshift * 1e-3); image_add_crystal(image, cr); + return 1; } @@ -201,8 +429,8 @@ static char *base_indexer_str(IndexingMethod indm) strcpy(str, "simulation"); break; - case INDEXING_DEBUG : - strcpy(str, "debug"); + case INDEXING_FILE : + strcpy(str, "file"); break; default : @@ -238,7 +466,8 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell, struct xgandalf_options *xgandalf_opts, struct pinkIndexer_options* pinkIndexer_opts, struct felix_options *felix_opts, - struct taketwo_options *taketwo_opts) + struct taketwo_options *taketwo_opts, + char *filename) { char *str; IndexingMethod in = *m; @@ -266,8 +495,8 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell, priv = xds_prepare(m, cell); break; - case INDEXING_DEBUG : - priv = (IndexingPrivate *)strdup("Hello!"); + case INDEXING_FILE : + priv = skip_prepare(filename); break; case INDEXING_FELIX : @@ -320,7 +549,8 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell, struct taketwo_options *ttopts, struct xgandalf_options *xgandalf_opts, struct pinkIndexer_options *pinkIndexer_opts, - struct felix_options *felix_opts) + struct felix_options *felix_opts, + char *filename) { int i, n; char **method_strings; @@ -417,7 +647,8 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell, xgandalf_opts, pinkIndexer_opts, felix_opts, - ttopts); + ttopts, + filename); if ( ipriv->engine_private[i] == NULL ) return NULL; @@ -518,8 +749,9 @@ void cleanup_indexing(IndexingPrivate *ipriv) felix_cleanup(ipriv->engine_private[n]); break; - case INDEXING_DEBUG : + case INDEXING_FILE : free(ipriv->engine_private[n]); + delete_all(); break; case INDEXING_TAKETWO : @@ -645,9 +877,9 @@ static int try_indexer(struct image *image, IndexingMethod indm, r = run_xds(image, mpriv); break; - case INDEXING_DEBUG : - set_last_task(last_task, "indexing:debug"); - r = debug_index(image); + case INDEXING_FILE : + set_last_task(last_task, "indexing:file"); + r = skip_index(image,mpriv); break; case INDEXING_FELIX : @@ -1080,9 +1312,9 @@ IndexingMethod get_indm_from_string_2(const char *str, int *err) method = INDEXING_SIMULATION; return method; - } else if ( strcmp(bits[i], "debug") == 0) { + } else if ( strcmp(bits[i], "file") == 0) { if ( have_method ) return warn_method(str); - method = INDEXING_DEBUG; + method = INDEXING_FILE; return method; } else if ( strcmp(bits[i], "latt") == 0) { diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h index 0c899199..bd5be68e 100644 --- a/libcrystfel/src/index.h +++ b/libcrystfel/src/index.h @@ -77,7 +77,7 @@ typedef enum { INDEXING_FELIX = 4, /**< Invoke Felix program */ INDEXING_XDS = 5, /**< Invoke XDS program (NB not nXDS) */ INDEXING_SIMULATION = 6, /**< Dummy value for simulated data */ - INDEXING_DEBUG = 7, /**< Results injector for debugging */ + INDEXING_FILE = 7, /**< Results injector for debugging */ INDEXING_ASDF = 8, /**< Use built-in ASDF algorithm */ INDEXING_TAKETWO = 9, /**< Use built-in TakeTwo algorithm */ INDEXING_XGANDALF = 10, /**< Use XGANDALF (via optional library) */ @@ -159,7 +159,8 @@ extern IndexingPrivate *setup_indexing(const char *methods, UnitCell *cell, struct taketwo_options *ttopts, struct xgandalf_options *xgandalf_opts, struct pinkIndexer_options *pinkIndexer_opts, - struct felix_options *felix_opts); + struct felix_options *felix_opts, + char *filename); extern const IndexingMethod *indexing_methods(IndexingPrivate *p, int *n); diff --git a/libcrystfel/src/uthash.h b/libcrystfel/src/uthash.h new file mode 100755 index 00000000..5e5866a3 --- /dev/null +++ b/libcrystfel/src/uthash.h @@ -0,0 +1,1150 @@ +/* +Copyright (c) 2003-2018, Troy D. Hanson http://troydhanson.github.com/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.1.0 + +#include /* memcmp, memset, strlen */ +#include /* ptrdiff_t */ +#include /* exit */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE(x) +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */ +#if defined(_WIN32) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#include +#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif +#elif defined(__GNUC__) && !defined(__VXWORKS__) +#include +#else +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#endif + +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifdef uthash_memcmp +/* This warning will not catch programs that define uthash_memcmp AFTER including uthash.h. */ +#warning "uthash_memcmp is deprecated; please use HASH_KEYCMP instead" +#else +#define uthash_memcmp(a,b,n) memcmp(a,b,n) +#endif + +#ifndef HASH_KEYCMP +#define HASH_KEYCMP(a,b,n) uthash_memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif + +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FCN(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head,oomed) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) + +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ +do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +} while (0) +#define HASH_ADD_STR(head,strfield,add) \ +do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +} while (0) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ +do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ +} while (0) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#include /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_prev); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head,where) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ +#ifdef HASH_FUNCTION +#define HASH_FCN HASH_FUNCTION +#else +#define HASH_FCN HASH_JEN +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char*)(key); \ + hashv = 0; \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ +do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + 2UL * (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ + )) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ -- cgit v1.2.3 From f34c46f087108a293d471eec4235b292a13daa69 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Sun, 19 Jul 2020 21:27:02 +0200 Subject: last minute changes --- libcrystfel/src/index.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index ab451c41..3ac3dad5 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -68,6 +68,7 @@ struct skip_private { char path_to_sol[50]; + UnitCell *cellTemplate; float solutions[]; }; @@ -153,7 +154,7 @@ static void show_indexing_flags(IndexingFlags flags) } -void *skip_prepare(char *solution_filename) +void *skip_prepare(char *solution_filename, UnitCell *cell) { FILE *fh; int nlines; @@ -277,6 +278,9 @@ void *skip_prepare(char *solution_filename) { dp->solutions[k] = params[k]; } + + + dp->cellTemplate = cell; free(params); @@ -366,6 +370,9 @@ static int skip_index(struct image *image, void *mpriv) cr = crystal_new(); cell = cell_new(); cell_set_reciprocal(cell, asx * 1e9, asy * 1e9, asz* 1e9, bsx * 1e9, bsy * 1e9, bsz * 1e9, csx * 1e9, csy * 1e9, csz* 1e9); + 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)); crystal_set_cell(cr, cell); crystal_set_det_shift(cr, xshift * 1e-3, yshift * 1e-3); @@ -496,7 +503,7 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell, break; case INDEXING_FILE : - priv = skip_prepare(filename); + priv = skip_prepare(filename, cell); break; case INDEXING_FELIX : -- cgit v1.2.3 From 0b6ce92886424133a6a61bc0613fe89c2d359fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Bu=CC=88cker?= Date: Wed, 5 Aug 2020 11:18:04 +0200 Subject: adding some versbosity to file indexer --- libcrystfel/src/index.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 3ac3dad5..ddd25a4b 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -184,9 +184,12 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) fh = fopen(path_to_sol, "r"); if ( fh == NULL ) { - ERROR("indexing.sol not found by skip_prepare\n"); + ERROR("%s not found by skip_prepare in %s\n", path_to_sol, cwd); return 0; } + else { + fprintf("Reading solution file %s from %s\n", path_to_sol, cwd); + } nlines = ncrystals_in_sol(path_to_sol); nparams_per_line = 11; //There are 9 vector component and 2 detector shifts excluding filename and event @@ -310,6 +313,8 @@ int ncrystals_in_sol(char *path) // Close the file fclose(fh); + printf("Found indexing file %s containing %d lines. \n", path, count); + return count; } -- cgit v1.2.3 From 8aa94ecb8179de2e38ce2a7f135df1eb97eb0b80 Mon Sep 17 00:00:00 2001 From: Robert Buecker Date: Wed, 5 Aug 2020 12:53:29 +0200 Subject: hotfix for from-file indexer --- libcrystfel/src/index.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index ddd25a4b..1e8820d7 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -160,7 +160,7 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) int nlines; int nparams_in_solution; int nparams_per_line; - int nparams; + int nentries; char *filename[35]; //??? is that correct char *event_path[35]; //??? is that correct int event_dim; @@ -188,19 +188,21 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) return 0; } else { - fprintf("Reading solution file %s from %s\n", path_to_sol, cwd); + STATUS("Found solution file %s at %s\n", path_to_sol, cwd); } nlines = ncrystals_in_sol(path_to_sol); - nparams_per_line = 11; //There are 9 vector component and 2 detector shifts excluding filename and event - nparams_in_solution = nlines*nparams_per_line; - nparams = nlines*(nparams_per_line+3); + nparams_per_line = 11; /* There are 9 vector components and 2 detector shifts */ + nparams_in_solution = nlines*nparams_per_line; /* total crystal parameters in solution file */ + nentries = nlines*(nparams_per_line+3); /* total entries in solution file */ float *params = malloc(nparams_in_solution * sizeof( float)); + STATUS("Parsing solution file containing %d lines...\n", nlines); + //Reads indexing solutions int j = 0; //index that follows the solution parameter - for(int i = 0; i < nparams; i++) + for(int i = 0; i < nentries; i++) { current_line = i/(nparams_per_line+3); @@ -270,15 +272,20 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) fclose(fh); + STATUS("Solution file parsing done. Have %d parameters and %d total entries.\n", nparams_in_solution, nentries) + struct skip_private *dp; - dp = (struct skip_private *) malloc( sizeof(struct skip_private) + nparams * sizeof( float) ); + dp = (struct skip_private *) malloc( sizeof(struct skip_private) + nentries * sizeof( float) ); if ( dp == NULL ) return NULL; memcpy(dp->path_to_sol, path_to_sol, sizeof path_to_sol); - for (int k = 0; k < nparams; k++) + for (int k = 0; k < nparams_in_solution; k++) { + if ( (k % 1000) == 0 ){ + STATUS("Read %d parameters.\n", k); + } dp->solutions[k] = params[k]; } @@ -287,6 +294,8 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) free(params); + STATUS("Solution lookup table initialized!\n"); + return (void *)dp; } @@ -313,7 +322,7 @@ int ncrystals_in_sol(char *path) // Close the file fclose(fh); - printf("Found indexing file %s containing %d lines. \n", path, count); + // STATUS("Found indexing file %s containing %d lines. \n", path, count); return count; -- cgit v1.2.3 From a4b8e131cd253f947148eae96c311edf532e9a37 Mon Sep 17 00:00:00 2001 From: Robert Buecker Date: Thu, 6 Aug 2020 10:52:47 +0200 Subject: changed status messages for file indexer --- libcrystfel/src/index.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 1e8820d7..2b5907ba 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -184,7 +184,7 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) fh = fopen(path_to_sol, "r"); if ( fh == NULL ) { - ERROR("%s not found by skip_prepare in %s\n", path_to_sol, cwd); + ERROR("%s not found by skip_prepare in %s\n", path_to_sol, cwd); return 0; } else { @@ -283,9 +283,6 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) for (int k = 0; k < nparams_in_solution; k++) { - if ( (k % 1000) == 0 ){ - STATUS("Read %d parameters.\n", k); - } dp->solutions[k] = params[k]; } @@ -362,7 +359,9 @@ static int skip_index(struct image *image, void *mpriv) HASH_FIND(hh, line_hash, &item->key, sizeof(struct record_key_t), p); /* id already in the hash? */ if (p==NULL) { - printf("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); + /* + STATUS("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); + */ return 0; } -- cgit v1.2.3 From 3926cfee958f2b3687997f22881c6d2593bbd3b7 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Mon, 14 Sep 2020 23:58:00 -0400 Subject: Removed global variable, include profile_radius and diff_limit in sol file, cleaned up warning messages, not working yet for multi-crystals --- libcrystfel/src/index.c | 265 ++++++++++++++++++++++++++---------------------- 1 file changed, 145 insertions(+), 120 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 2b5907ba..0150787a 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "image.h" #include "utils.h" @@ -65,28 +66,28 @@ /** \file index.h */ +#define NPARAMS_PER_LINE 13 // There are 9 vector components, 2 detector shifts, 1 profile radius, 1 resolution limit +#define NKEYS_PER_LINE 4 // The keys are the filename, event path, event dim and crystal number + struct skip_private { - char path_to_sol[50]; - UnitCell *cellTemplate; - float solutions[]; + UnitCell *cellTemplate; + struct record_t *sol_hash; }; -struct record_key_t{ //added +struct record_key_t{ //Hash table keys char filename[100]; - char event_path[35]; + char event_path[100]; int event_dim; + int crystal_number; }; -struct record_t{ //added +struct record_t{ //Hash table struct record_key_t key; - int line; + float solution[NPARAMS_PER_LINE]; UT_hash_handle hh; }; -//declared as global variable -struct record_t *line_hash = NULL; //added - struct _indexingprivate { IndexingFlags flags; @@ -98,22 +99,24 @@ struct _indexingprivate void **engine_private; }; -void delete_all() { - struct record_t *current_line, *tmp; +void print_struct(struct record_t *sol_hash) { + struct record_t *s; + s = (struct record_t *)malloc(sizeof *s); + memset(s, 0, sizeof *s); - HASH_ITER(hh, line_hash, current_line, tmp) { - HASH_DEL(line_hash, current_line); - free(current_line); - } + for(s=sol_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { + printf("This entry corresponds to event %s//%d and crystal_number %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.crystal_number, s->key.filename); + } } -void print_struct() { +void full_print_struct(struct record_t *sol_hash) { struct record_t *s; s = (struct record_t *)malloc(sizeof *s); memset(s, 0, sizeof *s); - for(s=line_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { - printf("The line is event_path %s and event_dim %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.filename); + for(s=sol_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { + printf("This entry corresponds to event %s//%d and crystal_number %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.crystal_number, s->key.filename); + printf("The solution parameters are %e %e %e %e %e %e %e %e %e %e %e %e %e \n", s->solution[0], s->solution[1], s->solution[2], s->solution[3], s->solution[4], s->solution[5], s->solution[6], s->solution[7], s->solution[8], s->solution[9], s->solution[10], s->solution[11], s->solution[12]); } } @@ -137,7 +140,6 @@ static void set_last_task(char *lt, const char *task) strcpy(lt, task); } - static void show_indexing_flags(IndexingFlags flags) { STATUS("Indexing parameters:\n"); @@ -153,30 +155,60 @@ static void show_indexing_flags(IndexingFlags flags) onoff(flags & INDEXING_RETRY)); } +int ncrystals_in_sol(char *path) +{ + FILE *fh; + int count = 0; // Line counter (result) + char c; // To store a character read from file + + fh = fopen(path, "r"); + + if ( fh == NULL ) { + ERROR("%s not found by ncrystals_in_sol\n",path); + return 0; + } + + for (c = getc(fh); c != EOF; c = getc(fh)) + if (c == '\n') // Increment count if this character is newline + count = count + 1; + + //For the last line, which has no \n at the end + count = count + 1; + + // Close the file + fclose(fh); + + // STATUS("Found indexing file %s containing %d lines. \n", path, count); + + return count; + +} + void *skip_prepare(char *solution_filename, UnitCell *cell) { FILE *fh; int nlines; int nparams_in_solution; - int nparams_per_line; int nentries; - char *filename[35]; //??? is that correct - char *event_path[35]; //??? is that correct - int event_dim; + char filename[100]; + char event_path[100]; + int event_dim; + int crystal_number; int current_line; int position_in_current_line; - struct record_t *item; + struct record_t *sol_hash = NULL; + struct record_t *item = NULL; + float params[NPARAMS_PER_LINE]; + char path_to_sol[50],extension[10]; + char cwd[PATH_MAX]; //Assembling solution file name from input file name to crystfel - char path_to_sol[50],extension[10]; strcpy(path_to_sol,"../"); strcpy(extension,".sol"); - strtok(solution_filename, "."); //Takes the first part of the list name (before the .) strcat(path_to_sol, strtok(solution_filename, ".") ); //Add .sol at the previously splitted name strcat(path_to_sol, extension ); - char cwd[PATH_MAX]; if (getcwd(cwd, sizeof(cwd)) != NULL) { //printf("Path where skip_prepare is ran: %s\n", cwd); } @@ -192,22 +224,19 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) } nlines = ncrystals_in_sol(path_to_sol); - nparams_per_line = 11; /* There are 9 vector components and 2 detector shifts */ - nparams_in_solution = nlines*nparams_per_line; /* total crystal parameters in solution file */ - nentries = nlines*(nparams_per_line+3); /* total entries in solution file */ + nparams_in_solution = nlines*NPARAMS_PER_LINE; /* total crystal parameters in solution file */ + nentries = nlines*(NPARAMS_PER_LINE+NKEYS_PER_LINE); /* total entries in solution file */ - float *params = malloc(nparams_in_solution * sizeof( float)); - STATUS("Parsing solution file containing %d lines...\n", nlines); //Reads indexing solutions - int j = 0; //index that follows the solution parameter + int j = 0; //index that follows the solution parameter [0,NPARAMS_PER_LINE] for(int i = 0; i < nentries; i++) { - current_line = i/(nparams_per_line+3); + current_line = i/(NPARAMS_PER_LINE+NKEYS_PER_LINE); - position_in_current_line = (i)%(nparams_per_line+3); + position_in_current_line = (i)%(NPARAMS_PER_LINE+NKEYS_PER_LINE); if (position_in_current_line == 0){ @@ -225,106 +254,84 @@ void *skip_prepare(char *solution_filename, UnitCell *cell) if (position_in_current_line == 1){ if ( fscanf(fh, "%s", event_path) != 1 ) { - printf("Failed to read an event_path from indexing.sol with skip_prepare\n"); + printf("Failed to read an event path from indexing.sol with skip_prepare\n"); return 0; } } - + if (position_in_current_line == 2){ + if ( fscanf(fh, "%d", &event_dim) != 1 ) { - printf("Failed to read an event from indexing.sol with skip_prepare\n"); + printf("Failed to read an event dim from indexing.sol with skip_prepare\n"); + return 0; + } + } + + if (position_in_current_line == 3){ + if ( fscanf(fh, "%d", &crystal_number) != 1 ) { + printf("Failed to read a crystal number from indexing.sol with skip_prepare\n"); + return 0; + } + } + + if (position_in_current_line > 3){ + if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { + printf("Failed to read a parameter from indexing.sol with skip_prepare\n"); return 0; } + j+=1; + + + } + + if (j == (NPARAMS_PER_LINE) ){ - //Prepare to add to the hash table once an event is read + //Prepare to add to the hash table item = (struct record_t *)malloc(sizeof *item); memset(item, 0, sizeof *item); strcpy(item->key.filename, filename); strcpy(item->key.event_path, event_path); item->key.event_dim = event_dim; - item->line=current_line; + item->key.crystal_number = crystal_number; + for (int k = 0; k < NPARAMS_PER_LINE; k++){ + item->solution[k] = params[k]; + } //Verify the uniqueness of the key struct record_t *uniqueness_test; - HASH_FIND(hh, line_hash, &item->key, sizeof(struct record_key_t), uniqueness_test); /* id already in the hash? */ + HASH_FIND(hh, sol_hash, &item->key, sizeof(struct record_key_t), uniqueness_test); // id already in the hash? if (uniqueness_test==NULL) { //If not in the table, add - HASH_ADD(hh, line_hash, key, sizeof(struct record_key_t), item); + HASH_ADD(hh, sol_hash, key, sizeof(struct record_key_t), item); } else{ //If already in the table, break with error - printf("Keys to the data must be unique! Verify the combination filename, event_path, event_dim"); + printf("Keys to the data must be unique! Verify the combination filename, event, crystal_number"); return 0; } + j=0; - - } - - if (position_in_current_line > 2){ - if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { - printf("Failed to read a parameter from indexing.sol with skip_prepare\n"); - return 0; - } - j+=1; } } fclose(fh); - + STATUS("Solution file parsing done. Have %d parameters and %d total entries.\n", nparams_in_solution, nentries) struct skip_private *dp; - dp = (struct skip_private *) malloc( sizeof(struct skip_private) + nentries * sizeof( float) ); + dp = (struct skip_private *) malloc( sizeof(struct skip_private)); if ( dp == NULL ) return NULL; - - memcpy(dp->path_to_sol, path_to_sol, sizeof path_to_sol); - - for (int k = 0; k < nparams_in_solution; k++) - { - dp->solutions[k] = params[k]; - } - dp->cellTemplate = cell; - - free(params); + dp->sol_hash = sol_hash; STATUS("Solution lookup table initialized!\n"); return (void *)dp; } -int ncrystals_in_sol(char *path) -{ - FILE *fh; - int count = 0; // Line counter (result) - char c; // To store a character read from file - - fh = fopen(path, "r"); - - if ( fh == NULL ) { - ERROR("%s not found by ncrystals_in_sol\n",path); - return 0; - } - - for (c = getc(fh); c != EOF; c = getc(fh)) - if (c == '\n') // Increment count if this character is newline - count = count + 1; - - //For the last line, which has no \n at the end - count = count + 1; - - // Close the file - fclose(fh); - - // STATUS("Found indexing file %s containing %d lines. \n", path, count); - - return count; - -} - //Fonction from pinkindexer.c to update the detector center of individual crystals //hack for electron crystallography while crystal_set_det_shift is not working approprietly static void update_detector(struct detector *det, double xoffs, double yoffs) @@ -338,15 +345,13 @@ static void update_detector(struct detector *det, double xoffs, double yoffs) } } -static int skip_index(struct image *image, void *mpriv) +static int skip_index(struct image *image, void *mpriv, int crystal_number) { Crystal *cr; UnitCell *cell; - float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz, xshift, yshift; - int serial; - int nparams_per_line; - struct record_t *item, *p; - int line_number; + float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz, xshift, yshift, profile_radius, resolution_limit; + struct record_t *item, *p, *pprime; + float *sol; struct skip_private *dp = (struct skip_private *)mpriv; @@ -356,29 +361,29 @@ static int skip_index(struct image *image, void *mpriv) strcpy(item->key.filename, image->filename); strcpy(item->key.event_path, *image->event->path_entries); item->key.event_dim = *image->event->dim_entries; + item->key.crystal_number = crystal_number; - HASH_FIND(hh, line_hash, &item->key, sizeof(struct record_key_t), p); /* id already in the hash? */ + HASH_FIND(hh, dp->sol_hash, &item->key, sizeof(struct record_key_t), p); //id already in the hash? if (p==NULL) { - /* - STATUS("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); - */ + //STATUS("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); return 0; } - line_number = p->line; - nparams_per_line = 11; - - asx = dp->solutions[(line_number * nparams_per_line) + 0]; - asy = dp->solutions[(line_number * nparams_per_line) + 1]; - asz = dp->solutions[(line_number * nparams_per_line) + 2]; - bsx = dp->solutions[(line_number * nparams_per_line) + 3]; - bsy = dp->solutions[(line_number * nparams_per_line) + 4]; - bsz = dp->solutions[(line_number * nparams_per_line) + 5]; - csx = dp->solutions[(line_number * nparams_per_line) + 6]; - csy = dp->solutions[(line_number * nparams_per_line) + 7]; - csz = dp->solutions[(line_number * nparams_per_line) + 8]; - xshift = dp->solutions[(line_number * nparams_per_line) + 9]; - yshift = dp->solutions[(line_number * nparams_per_line) + 10]; + sol = &(p->solution)[0]; + + asx = sol[0]; + asy = sol[1]; + asz = sol[2]; + bsx = sol[3]; + bsy = sol[4]; + bsz = sol[5]; + csx = sol[6]; + csy = sol[7]; + csz = sol[8]; + xshift = sol[9]; + yshift = sol[10]; + profile_radius = sol[11]; + resolution_limit = sol[12]; cr = crystal_new(); cell = cell_new(); @@ -390,9 +395,29 @@ static int skip_index(struct image *image, void *mpriv) crystal_set_cell(cr, cell); crystal_set_det_shift(cr, xshift * 1e-3, yshift * 1e-3); update_detector(image->det, xshift * 1e-3, yshift * 1e-3); + crystal_set_profile_radius(cr, profile_radius*1e9); + crystal_set_resolution_limit(cr, resolution_limit*1e9); 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 record_key_t), pprime); //id already in the hash? + if (pprime==NULL) { + + //If no more crystal, done + return 1; + } + else{ + //If more crystals, recursive call for next crystal in line + skip_index(image,mpriv,crystal_number+1); + } + + + dp->sol_hash = NULL; //Clean up local copy of the hash table + + return 1; + } @@ -771,7 +796,6 @@ void cleanup_indexing(IndexingPrivate *ipriv) case INDEXING_FILE : free(ipriv->engine_private[n]); - delete_all(); break; case INDEXING_TAKETWO : @@ -899,7 +923,8 @@ static int try_indexer(struct image *image, IndexingMethod indm, case INDEXING_FILE : set_last_task(last_task, "indexing:file"); - r = skip_index(image,mpriv); + int crystal_number = 0; + r = skip_index(image,mpriv,crystal_number); break; case INDEXING_FELIX : -- cgit v1.2.3 From b11033a649afff30254804d9035ee9ccb67f044d Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Wed, 16 Sep 2020 02:31:58 -0400 Subject: fromfile indexer in a separate file --- libcrystfel/src/fromfile.c | 364 +++++++++++++++++++++++++++++++++++++++++++++ libcrystfel/src/fromfile.h | 73 +++++++++ libcrystfel/src/index.c | 314 +------------------------------------- 3 files changed, 440 insertions(+), 311 deletions(-) create mode 100644 libcrystfel/src/fromfile.c create mode 100644 libcrystfel/src/fromfile.h (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c new file mode 100644 index 00000000..8dcb92c1 --- /dev/null +++ b/libcrystfel/src/fromfile.c @@ -0,0 +1,364 @@ +/* + * fromfile.c + * + * Perform indexing from solution file + * + * + * Authors: + * 2020 Pascal Hogan-Lamarre + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see . + * + */ + +#include "image.h" +#include "detector.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "uthash.h" + +/** \file fromfile.h */ + +/* There are 9 vector components, + * 2 detector shifts, 1 profile radius, + * 1 resolution limit */ +#define NPARAMS_PER_LINE 13 +/* The keys are the filename, + * event path, event dim and crystal number */ +#define NKEYS_PER_LINE 4 + +struct fromfile_private +{ + UnitCell *cellTemplate; + struct fromfile_entries *sol_hash; +}; + +struct fromfile_keys +{ + char filename[100]; + char event_path[100]; + int event_dim; + int crystal_number; +}; + +struct fromfile_entries +{ + struct fromfile_keys key; + float solution[NPARAMS_PER_LINE]; + UT_hash_handle hh; +}; + +void print_struct(struct fromfile_entries *sol_hash) +{ + struct fromfile_entries *s; + s = (struct fromfile_entries *)malloc(sizeof *s); + memset(s, 0, sizeof *s); + + for( s=sol_hash; s != NULL; s=(struct fromfile_entries*)(s->hh.next) ) { + printf("File %s, event %s//%d and crystal_number %d \n", + s->key.filename, s->key.event_path, + s->key.event_dim, s->key.crystal_number); + } +} + +void full_print_struct(struct fromfile_entries *sol_hash) +{ + struct fromfile_entries *s; + s = (struct fromfile_entries *)malloc(sizeof *s); + memset(s, 0, sizeof *s); + + for( s=sol_hash; s != NULL; s=(struct fromfile_entries*)(s->hh.next) ) { + printf("File %s, event %s//%d and crystal_number %d \n", + s->key.filename, s->key.event_path, + s->key.event_dim, s->key.crystal_number); + + printf("Solution parameters:\n"); + for( int i = 0; i < NPARAMS_PER_LINE; i++ ){ + printf("%e", s->solution[i]); + } + printf("\n"); + } +} + +int ncrystals_in_sol(char *path) +{ + FILE *fh; + int count = 0; /* Line counter (result) */ + char c; /* To store a character read from file */ + + fh = fopen(path, "r"); + + if ( fh == NULL ) { + ERROR("%s not found by ncrystals_in_sol\n",path); + return 0; + } + + for ( c = getc(fh); c != EOF; c = getc(fh) ){ + if ( c == '\n' ){ + count = count + 1; + } + } + + /* For the last line, which has no \n at the end*/ + count = count + 1; + + fclose(fh); + + return count; + +} + +void *fromfile_prepare(char *solution_filename, UnitCell *cell) +{ + FILE *fh; + int nlines; + int nparams_in_solution; + int nentries; + char filename[100]; + char event_path[100]; + int event_dim; + 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]; + char path_to_sol[50],extension[10]; + char cwd[PATH_MAX]; + + /* Assembling solution file name from input file name*/ + strcpy(path_to_sol, "../"); + strcpy(extension, ".sol"); + strcat(path_to_sol, strtok(solution_filename, ".")); + strcat(path_to_sol, extension); + + if (getcwd(cwd, sizeof(cwd)) != NULL) { + ERROR("Cannot identify current directory\n"); + } + + fh = fopen(path_to_sol, "r"); + + if ( fh == NULL ) { + ERROR("%s not found by fromfile_prepare in %s\n", path_to_sol, cwd); + return 0; + } + else { + STATUS("Found solution file %s at %s\n", path_to_sol, cwd); + } + + nlines = ncrystals_in_sol(path_to_sol); + /* 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++) + { + + 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 ){ + if ( fscanf(fh, "%s", filename) != 1 ) { + if ( current_line == (nlines-1) ){ + break; + } + else{ + printf("Failed to read a filename\n"); + return 0; + } + } + } + + if ( position_in_current_line == 1 ){ + + if ( fscanf(fh, "%s", event_path) != 1 ) { + printf("Failed to read an event path\n"); + return 0; + } + } + + if ( position_in_current_line == 2 ){ + + if ( fscanf(fh, "%d", &event_dim) != 1 ) { + printf("Failed to read an event dim\n"); + return 0; + } + } + + if ( position_in_current_line == 3 ){ + if ( fscanf(fh, "%d", &crystal_number) != 1 ) { + printf("Failed to read a crystal number\n"); + return 0; + } + } + + if ( position_in_current_line > 3 ){ + if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { + printf("Failed to read a parameter\n"); + return 0; + } + j+=1; + } + + if ( j == (NPARAMS_PER_LINE) ){ + + /* 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_path, event_path); + item->key.event_dim = event_dim; + item->key.crystal_number = crystal_number; + for ( int k = 0; k < NPARAMS_PER_LINE; k++){ + item->solution[k] = params[k]; + } + + /* Verify the uniqueness of the key */ + struct fromfile_entries *uniqueness_test; + HASH_FIND(hh, sol_hash, &item->key, + sizeof(struct fromfile_keys), uniqueness_test); + if (uniqueness_test==NULL) { + HASH_ADD(hh, sol_hash, key, sizeof(struct fromfile_keys), item); + } + else{ + printf("Keys must be unique! Verify the combinations"); + return 0; + } + + j=0; + + } + } + + fclose(fh); + + 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; + } + + dp->cellTemplate = cell; + dp->sol_hash = sol_hash; + + STATUS("Solution lookup table initialized!\n"); + + return (void *)dp; +} + +static void update_detector(struct detector *det, double xoffs, double yoffs) +{ + int i; + + for ( i = 0; i < det->n_panels; i++ ) { + struct panel *p = &det->panels[i]; + p->cnx += xoffs * p->res; + p->cny += yoffs * p->res; + } +} + +int fromfile_index(struct image *image, void *mpriv, int crystal_number) +{ + Crystal *cr; + UnitCell *cell; + float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz; + float xshift, yshift, profile_radius, resolution_limit; + struct fromfile_entries *item, *p, *pprime; + float *sol; + + struct fromfile_private *dp = (struct fromfile_private *)mpriv; + + /* Look up the hash table */ + item = (struct fromfile_entries *)malloc(sizeof *item); + memset(item, 0, sizeof *item); + strcpy(item->key.filename, image->filename); + strcpy(item->key.event_path, *image->event->path_entries); + item->key.event_dim = *image->event->dim_entries; + 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; + profile_radius = sol[11] * 1e9; + resolution_limit = sol[12] * 1e9; + + cr = crystal_new(); + 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)); + + crystal_set_cell(cr, cell); + crystal_set_det_shift(cr, xshift , yshift); + update_detector(image->det, xshift , yshift); + crystal_set_profile_radius(cr, profile_radius); + crystal_set_resolution_limit(cr, resolution_limit); + 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 ( pprime == NULL ) { + + /* If no more crystal, done */ + return 1; + } + else{ + /* If more crystals, recursive call for next crystal in line */ + fromfile_index(image, mpriv, crystal_number+1); + } + + dp->sol_hash = NULL; /* Clean up local copy */ + + return 1; + +} \ No newline at end of file diff --git a/libcrystfel/src/fromfile.h b/libcrystfel/src/fromfile.h new file mode 100644 index 00000000..dda976b5 --- /dev/null +++ b/libcrystfel/src/fromfile.h @@ -0,0 +1,73 @@ +/* + * fromfile.h + * + * Perform indexing from solution file + * + * + * Authors: + * 2020 Pascal Hogan-Lamarre + * + * This file is part of CrystFEL. + * + * CrystFEL is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * CrystFEL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CrystFEL. If not, see . + * + */ + +#ifndef FROMFILE_H +#define FROMFILE_H + + +#include "image.h" +#include "cell.h" +#include "uthash.h" + +/* There are 9 vector components, + * 2 detector shifts, 1 profile radius, + * 1 resolution limit */ +#define NPARAMS_PER_LINE 13 +/* The keys are the filename, + * event path, event dim and crystal number */ +#define NKEYS_PER_LINE 4 + +struct fromfile_private +{ + UnitCell *cellTemplate; + struct fromfile_entries *sol_hash; +}; + +struct fromfile_keys +{ + char filename[100]; + char event_path[100]; + int event_dim; + int crystal_number; +}; + +struct fromfile_entries +{ + struct fromfile_keys key; + float solution[NPARAMS_PER_LINE]; + UT_hash_handle hh; +}; + +extern void print_struct(struct fromfile_entries *sol_hash); + +extern void full_print_struct(struct fromfile_entries *sol_hash); + +extern void *fromfile_prepare(char *solution_filename, UnitCell *cell); + +extern int fromfile_index(struct image *image, void *mpriv, int crystal_number); + + +#endif /* FROMFILE_H */ \ No newline at end of file diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index 0150787a..c8e34b23 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -60,34 +60,13 @@ #include "taketwo.h" #include "xgandalf.h" #include "pinkindexer.h" +#include "fromfile.h" #include "uthash.h" /** \file index.h */ -#define NPARAMS_PER_LINE 13 // There are 9 vector components, 2 detector shifts, 1 profile radius, 1 resolution limit -#define NKEYS_PER_LINE 4 // The keys are the filename, event path, event dim and crystal number - -struct skip_private -{ - UnitCell *cellTemplate; - struct record_t *sol_hash; -}; - -struct record_key_t{ //Hash table keys - char filename[100]; - char event_path[100]; - int event_dim; - int crystal_number; -}; - -struct record_t{ //Hash table - struct record_key_t key; - float solution[NPARAMS_PER_LINE]; - UT_hash_handle hh; -}; - struct _indexingprivate { IndexingFlags flags; @@ -99,27 +78,6 @@ struct _indexingprivate void **engine_private; }; -void print_struct(struct record_t *sol_hash) { - struct record_t *s; - s = (struct record_t *)malloc(sizeof *s); - memset(s, 0, sizeof *s); - - for(s=sol_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { - printf("This entry corresponds to event %s//%d and crystal_number %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.crystal_number, s->key.filename); - } -} - -void full_print_struct(struct record_t *sol_hash) { - struct record_t *s; - s = (struct record_t *)malloc(sizeof *s); - memset(s, 0, sizeof *s); - - for(s=sol_hash; s != NULL; s=(struct record_t*)(s->hh.next)) { - printf("This entry corresponds to event %s//%d and crystal_number %d in file %s \n", s->key.event_path, s->key.event_dim, s->key.crystal_number, s->key.filename); - printf("The solution parameters are %e %e %e %e %e %e %e %e %e %e %e %e %e \n", s->solution[0], s->solution[1], s->solution[2], s->solution[3], s->solution[4], s->solution[5], s->solution[6], s->solution[7], s->solution[8], s->solution[9], s->solution[10], s->solution[11], s->solution[12]); - } -} - static const char *onoff(int a) { if ( a ) return "on"; @@ -155,272 +113,6 @@ static void show_indexing_flags(IndexingFlags flags) onoff(flags & INDEXING_RETRY)); } -int ncrystals_in_sol(char *path) -{ - FILE *fh; - int count = 0; // Line counter (result) - char c; // To store a character read from file - - fh = fopen(path, "r"); - - if ( fh == NULL ) { - ERROR("%s not found by ncrystals_in_sol\n",path); - return 0; - } - - for (c = getc(fh); c != EOF; c = getc(fh)) - if (c == '\n') // Increment count if this character is newline - count = count + 1; - - //For the last line, which has no \n at the end - count = count + 1; - - // Close the file - fclose(fh); - - // STATUS("Found indexing file %s containing %d lines. \n", path, count); - - return count; - -} - - -void *skip_prepare(char *solution_filename, UnitCell *cell) -{ - FILE *fh; - int nlines; - int nparams_in_solution; - int nentries; - char filename[100]; - char event_path[100]; - int event_dim; - int crystal_number; - int current_line; - int position_in_current_line; - struct record_t *sol_hash = NULL; - struct record_t *item = NULL; - float params[NPARAMS_PER_LINE]; - char path_to_sol[50],extension[10]; - char cwd[PATH_MAX]; - - //Assembling solution file name from input file name to crystfel - strcpy(path_to_sol,"../"); - strcpy(extension,".sol"); - strcat(path_to_sol, strtok(solution_filename, ".") ); //Add .sol at the previously splitted name - strcat(path_to_sol, extension ); - - if (getcwd(cwd, sizeof(cwd)) != NULL) { - //printf("Path where skip_prepare is ran: %s\n", cwd); - } - - fh = fopen(path_to_sol, "r"); - - if ( fh == NULL ) { - ERROR("%s not found by skip_prepare in %s\n", path_to_sol, cwd); - return 0; - } - else { - STATUS("Found solution file %s at %s\n", path_to_sol, cwd); - } - - nlines = ncrystals_in_sol(path_to_sol); - nparams_in_solution = nlines*NPARAMS_PER_LINE; /* total crystal parameters in solution file */ - nentries = nlines*(NPARAMS_PER_LINE+NKEYS_PER_LINE); /* total entries in solution file */ - - STATUS("Parsing solution file containing %d lines...\n", nlines); - - //Reads indexing solutions - int j = 0; //index that follows the solution parameter [0,NPARAMS_PER_LINE] - for(int i = 0; i < nentries; i++) - { - - 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){ - - if ( fscanf(fh, "%s", filename) != 1 ) { - if (current_line == (nlines-1)){ - break; - } - else{ - printf("Failed to read a filename from indexing.sol with skip_prepare\n"); - return 0; - } - } - } - - if (position_in_current_line == 1){ - - if ( fscanf(fh, "%s", event_path) != 1 ) { - printf("Failed to read an event path from indexing.sol with skip_prepare\n"); - return 0; - } - } - - if (position_in_current_line == 2){ - - if ( fscanf(fh, "%d", &event_dim) != 1 ) { - printf("Failed to read an event dim from indexing.sol with skip_prepare\n"); - return 0; - } - } - - if (position_in_current_line == 3){ - if ( fscanf(fh, "%d", &crystal_number) != 1 ) { - printf("Failed to read a crystal number from indexing.sol with skip_prepare\n"); - return 0; - } - } - - if (position_in_current_line > 3){ - if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { - printf("Failed to read a parameter from indexing.sol with skip_prepare\n"); - return 0; - } - j+=1; - - - } - - if (j == (NPARAMS_PER_LINE) ){ - - //Prepare to add to the hash table - item = (struct record_t *)malloc(sizeof *item); - memset(item, 0, sizeof *item); - strcpy(item->key.filename, filename); - strcpy(item->key.event_path, event_path); - item->key.event_dim = event_dim; - item->key.crystal_number = crystal_number; - for (int k = 0; k < NPARAMS_PER_LINE; k++){ - item->solution[k] = params[k]; - } - - //Verify the uniqueness of the key - struct record_t *uniqueness_test; - HASH_FIND(hh, sol_hash, &item->key, sizeof(struct record_key_t), uniqueness_test); // id already in the hash? - if (uniqueness_test==NULL) { - //If not in the table, add - HASH_ADD(hh, sol_hash, key, sizeof(struct record_key_t), item); - } - else{ - //If already in the table, break with error - printf("Keys to the data must be unique! Verify the combination filename, event, crystal_number"); - return 0; - } - - j=0; - - } - } - - fclose(fh); - - STATUS("Solution file parsing done. Have %d parameters and %d total entries.\n", nparams_in_solution, nentries) - - struct skip_private *dp; - dp = (struct skip_private *) malloc( sizeof(struct skip_private)); - - if ( dp == NULL ) return NULL; - - dp->cellTemplate = cell; - dp->sol_hash = sol_hash; - - STATUS("Solution lookup table initialized!\n"); - - return (void *)dp; -} - -//Fonction from pinkindexer.c to update the detector center of individual crystals -//hack for electron crystallography while crystal_set_det_shift is not working approprietly -static void update_detector(struct detector *det, double xoffs, double yoffs) -{ - int i; - - for (i = 0; i < det->n_panels; i++) { - struct panel *p = &det->panels[i]; - p->cnx += xoffs * p->res; - p->cny += yoffs * p->res; - } -} - -static int skip_index(struct image *image, void *mpriv, int crystal_number) -{ - Crystal *cr; - UnitCell *cell; - float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz, xshift, yshift, profile_radius, resolution_limit; - struct record_t *item, *p, *pprime; - float *sol; - - struct skip_private *dp = (struct skip_private *)mpriv; - - //Look up the hash table - item = (struct record_t *)malloc(sizeof *item); - memset(item, 0, sizeof *item); - strcpy(item->key.filename, image->filename); - strcpy(item->key.event_path, *image->event->path_entries); - item->key.event_dim = *image->event->dim_entries; - item->key.crystal_number = crystal_number; - - HASH_FIND(hh, dp->sol_hash, &item->key, sizeof(struct record_key_t), p); //id already in the hash? - if (p==NULL) { - //STATUS("Not indexing file %s, event %s %d \n", image->filename, *image->event->path_entries, *image->event->dim_entries); - return 0; - } - - sol = &(p->solution)[0]; - - asx = sol[0]; - asy = sol[1]; - asz = sol[2]; - bsx = sol[3]; - bsy = sol[4]; - bsz = sol[5]; - csx = sol[6]; - csy = sol[7]; - csz = sol[8]; - xshift = sol[9]; - yshift = sol[10]; - profile_radius = sol[11]; - resolution_limit = sol[12]; - - cr = crystal_new(); - cell = cell_new(); - cell_set_reciprocal(cell, asx * 1e9, asy * 1e9, asz* 1e9, bsx * 1e9, bsy * 1e9, bsz * 1e9, csx * 1e9, csy * 1e9, csz* 1e9); - 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)); - - crystal_set_cell(cr, cell); - crystal_set_det_shift(cr, xshift * 1e-3, yshift * 1e-3); - update_detector(image->det, xshift * 1e-3, yshift * 1e-3); - crystal_set_profile_radius(cr, profile_radius*1e9); - crystal_set_resolution_limit(cr, resolution_limit*1e9); - 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 record_key_t), pprime); //id already in the hash? - if (pprime==NULL) { - - //If no more crystal, done - return 1; - } - else{ - //If more crystals, recursive call for next crystal in line - skip_index(image,mpriv,crystal_number+1); - } - - - dp->sol_hash = NULL; //Clean up local copy of the hash table - - - return 1; - -} - - static char *base_indexer_str(IndexingMethod indm) { char *str; @@ -541,7 +233,7 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell, break; case INDEXING_FILE : - priv = skip_prepare(filename, cell); + priv = fromfile_prepare(filename, cell); break; case INDEXING_FELIX : @@ -924,7 +616,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, case INDEXING_FILE : set_last_task(last_task, "indexing:file"); int crystal_number = 0; - r = skip_index(image,mpriv,crystal_number); + r = fromfile_index(image, mpriv, crystal_number); break; case INDEXING_FELIX : -- cgit v1.2.3 From 689d86d0937332aa8577329d007b0dd31a2b73c4 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Wed, 16 Sep 2020 02:45:55 -0400 Subject: cleaning, remove double statements --- libcrystfel/src/fromfile.c | 21 ++++++++++----------- libcrystfel/src/fromfile.h | 32 +++----------------------------- 2 files changed, 13 insertions(+), 40 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index 8dcb92c1..eff997b5 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -45,13 +45,7 @@ #define NPARAMS_PER_LINE 13 /* The keys are the filename, * event path, event dim and crystal number */ -#define NKEYS_PER_LINE 4 - -struct fromfile_private -{ - UnitCell *cellTemplate; - struct fromfile_entries *sol_hash; -}; +#define NKEYS_PER_LINE 4 struct fromfile_keys { @@ -68,6 +62,12 @@ struct fromfile_entries UT_hash_handle hh; }; +struct fromfile_private +{ + UnitCell *cellTemplate; + struct fromfile_entries *sol_hash; +}; + void print_struct(struct fromfile_entries *sol_hash) { struct fromfile_entries *s; @@ -328,18 +328,18 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) profile_radius = sol[11] * 1e9; resolution_limit = sol[12] * 1e9; - cr = crystal_new(); 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(); crystal_set_cell(cr, cell); - crystal_set_det_shift(cr, xshift , yshift); - update_detector(image->det, xshift , yshift); crystal_set_profile_radius(cr, profile_radius); crystal_set_resolution_limit(cr, resolution_limit); + crystal_set_det_shift(cr, xshift , yshift); + update_detector(image->det, xshift , yshift); image_add_crystal(image, cr); /*Look for additional crystals*/ @@ -348,7 +348,6 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) sizeof(struct fromfile_keys), pprime); if ( pprime == NULL ) { - /* If no more crystal, done */ return 1; } diff --git a/libcrystfel/src/fromfile.h b/libcrystfel/src/fromfile.h index dda976b5..29d31aee 100644 --- a/libcrystfel/src/fromfile.h +++ b/libcrystfel/src/fromfile.h @@ -27,40 +27,14 @@ #ifndef FROMFILE_H #define FROMFILE_H +struct fromfile_keys; +struct fromfile_entries; +struct fromfile_private; #include "image.h" #include "cell.h" #include "uthash.h" -/* There are 9 vector components, - * 2 detector shifts, 1 profile radius, - * 1 resolution limit */ -#define NPARAMS_PER_LINE 13 -/* The keys are the filename, - * event path, event dim and crystal number */ -#define NKEYS_PER_LINE 4 - -struct fromfile_private -{ - UnitCell *cellTemplate; - struct fromfile_entries *sol_hash; -}; - -struct fromfile_keys -{ - char filename[100]; - char event_path[100]; - int event_dim; - int crystal_number; -}; - -struct fromfile_entries -{ - struct fromfile_keys key; - float solution[NPARAMS_PER_LINE]; - UT_hash_handle hh; -}; - extern void print_struct(struct fromfile_entries *sol_hash); extern void full_print_struct(struct fromfile_entries *sol_hash); -- cgit v1.2.3 From 5963ae8133473b5957f607cbc6fd9a5ccefa34f9 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Wed, 16 Sep 2020 21:09:40 -0400 Subject: modified the keys to use an event string --- libcrystfel/src/fromfile.c | 44 ++++++++++++++++---------------------------- 1 file changed, 16 insertions(+), 28 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index eff997b5..c87d5cbe 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -44,14 +44,13 @@ * 1 resolution limit */ #define NPARAMS_PER_LINE 13 /* The keys are the filename, - * event path, event dim and crystal number */ -#define NKEYS_PER_LINE 4 + * event, and crystal number */ +#define NKEYS_PER_LINE 3 struct fromfile_keys { char filename[100]; - char event_path[100]; - int event_dim; + char event[100]; int crystal_number; }; @@ -75,9 +74,9 @@ void print_struct(struct fromfile_entries *sol_hash) memset(s, 0, sizeof *s); for( s=sol_hash; s != NULL; s=(struct fromfile_entries*)(s->hh.next) ) { - printf("File %s, event %s//%d and crystal_number %d \n", - s->key.filename, s->key.event_path, - s->key.event_dim, s->key.crystal_number); + printf("File %s, event %s, and crystal_number %d \n", + s->key.filename, s->key.event, + s->key.crystal_number); } } @@ -88,9 +87,9 @@ void full_print_struct(struct fromfile_entries *sol_hash) memset(s, 0, sizeof *s); for( s=sol_hash; s != NULL; s=(struct fromfile_entries*)(s->hh.next) ) { - printf("File %s, event %s//%d and crystal_number %d \n", - s->key.filename, s->key.event_path, - s->key.event_dim, s->key.crystal_number); + 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++ ){ @@ -135,8 +134,7 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) int nparams_in_solution; int nentries; char filename[100]; - char event_path[100]; - int event_dim; + char event[100]; int crystal_number; int current_line; int position_in_current_line; @@ -197,28 +195,20 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) if ( position_in_current_line == 1 ){ - if ( fscanf(fh, "%s", event_path) != 1 ) { - printf("Failed to read an event path\n"); - return 0; - } - } - - if ( position_in_current_line == 2 ){ - - if ( fscanf(fh, "%d", &event_dim) != 1 ) { - printf("Failed to read an event dim\n"); + if ( fscanf(fh, "%s", event) != 1 ) { + printf("Failed to read an event\n"); return 0; } } - if ( position_in_current_line == 3 ){ + if ( position_in_current_line == 2 ){ if ( fscanf(fh, "%d", &crystal_number) != 1 ) { printf("Failed to read a crystal number\n"); return 0; } } - if ( position_in_current_line > 3 ){ + if ( position_in_current_line > 2 ){ if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { printf("Failed to read a parameter\n"); return 0; @@ -232,8 +222,7 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) item = (struct fromfile_entries *)malloc(sizeof *item); memset(item, 0, sizeof *item); strcpy(item->key.filename, filename); - strcpy(item->key.event_path, event_path); - item->key.event_dim = event_dim; + 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]; @@ -302,8 +291,7 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) item = (struct fromfile_entries *)malloc(sizeof *item); memset(item, 0, sizeof *item); strcpy(item->key.filename, image->filename); - strcpy(item->key.event_path, *image->event->path_entries); - item->key.event_dim = *image->event->dim_entries; + strcpy(item->key.event, get_event_string(image->event)); item->key.crystal_number = crystal_number; /* key already in the hash? */ -- cgit v1.2.3 From c97685fbeca127373ffb0a6cc1f2222e12a91f1e Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Wed, 16 Sep 2020 22:35:42 -0400 Subject: if-conditions that prevent modification of the profile_radius read from file --- libcrystfel/src/index.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index c8e34b23..e0e8ff05 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -664,7 +664,9 @@ static int try_indexer(struct image *image, IndexingMethod indm, Crystal *cr = image->crystals[this_crystal]; crystal_set_image(cr, image); - crystal_set_profile_radius(cr, 0.02e9); + if ( indm != INDEXING_FILE){ + crystal_set_profile_radius(cr, 0.02e9); + } crystal_set_mosaicity(cr, 0.0); /* Pre-refinement unit cell check if requested */ -- cgit v1.2.3 From 5c50243916af143a0d7c10792eacdfb97608a107 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Wed, 16 Sep 2020 22:45:56 -0400 Subject: if-conditions to prevent modifying the resolution limit value read in the solution file --- libcrystfel/src/integration.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/integration.c b/libcrystfel/src/integration.c index 3d8258c1..8a3c581e 100644 --- a/libcrystfel/src/integration.c +++ b/libcrystfel/src/integration.c @@ -1687,9 +1687,14 @@ void integrate_all_5(struct image *image, IntegrationMethod meth, saved_R * 5); } - res = estimate_resolution(crystal_get_cell(image->crystals[i]), + if ( image->indexed_by != INDEXING_FILE ){ + res = estimate_resolution(crystal_get_cell(image->crystals[i]), image->features); - crystal_set_resolution_limit(image->crystals[i], res); + crystal_set_resolution_limit(image->crystals[i], res); + } + else{ + res = crystal_get_resolution_limit(image->crystals[i]); + } list = predict_to_res(image->crystals[i], res+push_res); crystal_set_reflections(image->crystals[i], list); -- cgit v1.2.3 From 07787a409f8c152bf5ce224b67ae2ca8f99fb1d5 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Thu, 17 Sep 2020 00:29:28 -0400 Subject: multiple crystal per shot implemented (to be tested) --- libcrystfel/src/fromfile.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index c87d5cbe..f79bc0d1 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -283,6 +283,7 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz; float xshift, yshift, profile_radius, resolution_limit; struct fromfile_entries *item, *p, *pprime; + int ncryst = 0; float *sol; struct fromfile_private *dp = (struct fromfile_private *)mpriv; @@ -323,6 +324,7 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) cell_set_unique_axis(cell, cell_get_unique_axis(dp->cellTemplate)); cr = crystal_new(); + ncryst += 1; crystal_set_cell(cr, cell); crystal_set_profile_radius(cr, profile_radius); crystal_set_resolution_limit(cr, resolution_limit); @@ -335,17 +337,10 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) HASH_FIND(hh, dp->sol_hash, &item->key, sizeof(struct fromfile_keys), pprime); - if ( pprime == NULL ) { - /* If no more crystal, done */ - return 1; + if ( pprime != NULL ) { + ncryst += fromfile_index(image, mpriv, crystal_number+1); } - else{ - /* If more crystals, recursive call for next crystal in line */ - fromfile_index(image, mpriv, crystal_number+1); - } - - dp->sol_hash = NULL; /* Clean up local copy */ - - return 1; + + return ncryst; } \ No newline at end of file -- cgit v1.2.3 From 4489ee99f7b75d43e2c098822cfcb916847b47e1 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Thu, 17 Sep 2020 21:39:41 -0400 Subject: removed the crystal number key from the solution file, deduced during reading --- libcrystfel/src/fromfile.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index f79bc0d1..8555e0f4 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -43,9 +43,9 @@ * 2 detector shifts, 1 profile radius, * 1 resolution limit */ #define NPARAMS_PER_LINE 13 -/* The keys are the filename, - * event, and crystal number */ -#define NKEYS_PER_LINE 3 +/* The keys read from file + * are the filename, event */ +#define NKEYS_PER_LINE 2 struct fromfile_keys { @@ -176,6 +176,7 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) 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); @@ -200,15 +201,8 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) return 0; } } - - if ( position_in_current_line == 2 ){ - if ( fscanf(fh, "%d", &crystal_number) != 1 ) { - printf("Failed to read a crystal number\n"); - return 0; - } - } - if ( position_in_current_line > 2 ){ + if ( position_in_current_line > 1 ){ if ( fscanf(fh, "%e", ¶ms[j]) != 1 ) { printf("Failed to read a parameter\n"); return 0; @@ -231,13 +225,25 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) /* Verify the uniqueness of the key */ struct fromfile_entries *uniqueness_test; HASH_FIND(hh, sol_hash, &item->key, - sizeof(struct fromfile_keys), uniqueness_test); - if (uniqueness_test==NULL) { - HASH_ADD(hh, sol_hash, key, sizeof(struct fromfile_keys), item); + sizeof(struct fromfile_keys), uniqueness_test); + + if ( uniqueness_test == NULL ) { + HASH_ADD(hh, sol_hash, key, + sizeof(struct fromfile_keys), item); } else{ - printf("Keys must be unique! Verify the combinations"); - return 0; + 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); } j=0; -- cgit v1.2.3 From abbba986d43b1fa9d7107101d7b5432d6796009b Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Thu, 17 Sep 2020 23:25:25 -0400 Subject: read filename and event with dynamical allocation --- libcrystfel/src/fromfile.c | 63 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 12 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index 8555e0f4..05262458 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -127,27 +127,62 @@ int ncrystals_in_sol(char *path) } +char *read_unknown_string(FILE *fh){ + /* Source: "https://stackoverflow.com/questions/16870485/ + * how-can-i-read-an-input-string-of-unknown-length" */ + + char *str = NULL; + int ch; + size_t len = 0; + size_t size = 1; + + str = realloc(NULL, sizeof(char)*size); //size is start size + if ( !str ){ + ERROR("Can't reallocate string size") + } + + 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") + } + } + } + + return realloc(str, sizeof(char)*len); + +} + void *fromfile_prepare(char *solution_filename, UnitCell *cell) { FILE *fh; int nlines; int nparams_in_solution; int nentries; - char filename[100]; - char event[100]; + 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]; - char path_to_sol[50],extension[10]; char cwd[PATH_MAX]; /* Assembling solution file name from input file name*/ + char *path_to_sol; + size_t path_len; + char *core_name = strtok(solution_filename, "."); + char *extension = ".sol"; + path_len = sizeof(core_name) + sizeof(extension) + sizeof("../"); + path_to_sol = realloc(NULL, sizeof(char)*path_len); strcpy(path_to_sol, "../"); - strcpy(extension, ".sol"); - strcat(path_to_sol, strtok(solution_filename, ".")); + strcat(path_to_sol, core_name); strcat(path_to_sol, extension); if (getcwd(cwd, sizeof(cwd)) != NULL) { @@ -183,23 +218,26 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) position_in_current_line = (i)%(NPARAMS_PER_LINE+NKEYS_PER_LINE); if ( position_in_current_line == 0 ){ - if ( fscanf(fh, "%s", filename) != 1 ) { + + filename = read_unknown_string(fh); + + if ( !filename ){ if ( current_line == (nlines-1) ){ break; } - else{ printf("Failed to read a filename\n"); return 0; - } } + } if ( position_in_current_line == 1 ){ - - if ( fscanf(fh, "%s", event) != 1 ) { - printf("Failed to read an event\n"); + event = read_unknown_string(fh); + if ( !event ){ + printf("Failed to read a event\n"); return 0; } + } if ( position_in_current_line > 1 ){ @@ -232,6 +270,7 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) sizeof(struct fromfile_keys), item); } else{ + /* Look for the next available set of keys */ do { uniqueness_test = NULL; @@ -246,7 +285,7 @@ void *fromfile_prepare(char *solution_filename, UnitCell *cell) sizeof(struct fromfile_keys), item); } - j=0; + j=0; } } -- cgit v1.2.3 From f937b91c7c9016665efd0c38af1e0a5d21d41c99 Mon Sep 17 00:00:00 2001 From: Pascal Hogan-Lamarre Date: Sun, 4 Oct 2020 20:57:30 -0400 Subject: Solved problem concerning prof_radius and diff_lim calculation, prof_radius and diff_lim removed from sol file --- libcrystfel/src/fromfile.c | 10 ++++------ libcrystfel/src/index.c | 28 +++++++++++++++++++--------- libcrystfel/src/integration.c | 9 ++------- 3 files changed, 25 insertions(+), 22 deletions(-) (limited to 'libcrystfel/src') diff --git a/libcrystfel/src/fromfile.c b/libcrystfel/src/fromfile.c index 05262458..13044ebe 100644 --- a/libcrystfel/src/fromfile.c +++ b/libcrystfel/src/fromfile.c @@ -42,7 +42,7 @@ /* There are 9 vector components, * 2 detector shifts, 1 profile radius, * 1 resolution limit */ -#define NPARAMS_PER_LINE 13 +#define NPARAMS_PER_LINE 11 /* The keys read from file * are the filename, event */ #define NKEYS_PER_LINE 2 @@ -326,7 +326,7 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) Crystal *cr; UnitCell *cell; float asx, asy, asz, bsx, bsy, bsz, csx, csy, csz; - float xshift, yshift, profile_radius, resolution_limit; + float xshift, yshift; struct fromfile_entries *item, *p, *pprime; int ncryst = 0; float *sol; @@ -359,8 +359,6 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) csz = sol[8] * 1e9; xshift = sol[9] * 1e-3; yshift = sol[10] * 1e-3; - profile_radius = sol[11] * 1e9; - resolution_limit = sol[12] * 1e9; cell = cell_new(); cell_set_reciprocal(cell, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); @@ -371,8 +369,6 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) cr = crystal_new(); ncryst += 1; crystal_set_cell(cr, cell); - crystal_set_profile_radius(cr, profile_radius); - crystal_set_resolution_limit(cr, resolution_limit); crystal_set_det_shift(cr, xshift , yshift); update_detector(image->det, xshift , yshift); image_add_crystal(image, cr); @@ -382,6 +378,8 @@ int fromfile_index(struct image *image, void *mpriv, int crystal_number) 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); } diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index e0e8ff05..7b03ba3e 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -664,9 +664,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, Crystal *cr = image->crystals[this_crystal]; crystal_set_image(cr, image); - if ( indm != INDEXING_FILE){ - crystal_set_profile_radius(cr, 0.02e9); - } + crystal_set_profile_radius(cr, 0.02e9); crystal_set_mosaicity(cr, 0.0); /* Pre-refinement unit cell check if requested */ @@ -877,12 +875,14 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping, if ( ipriv == NULL ) return; - map_all_peaks(image); + if ( ipriv->methods[0] != INDEXING_FILE){ + map_all_peaks(image); + orig = image->features; + } + image->crystals = NULL; image->n_crystals = 0; - orig = image->features; - for ( n=0; nn_methods; n++ ) { int done = 0; @@ -890,7 +890,9 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping, int ntry = 0; int success = 0; - image->features = sort_peaks(orig); + if ( ipriv->methods[0] != INDEXING_FILE){ + image->features = sort_peaks(orig); + } do { @@ -906,7 +908,9 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping, } while ( !done ); - image_feature_list_free(image->features); + if ( ipriv->methods[0] != INDEXING_FILE){ + image_feature_list_free(image->features); + } /* Stop now if the pattern is indexed (don't try again for more * crystals with a different indexing method) */ @@ -917,13 +921,19 @@ void index_pattern_3(struct image *image, IndexingPrivate *ipriv, int *ping, } + if ( ipriv->methods[0] == INDEXING_FILE){ + map_all_peaks(image); + } + else{ + image->features = orig; + } + if ( n < ipriv->n_methods ) { image->indexed_by = ipriv->methods[n]; } else { image->indexed_by = INDEXING_NONE; } - image->features = orig; } diff --git a/libcrystfel/src/integration.c b/libcrystfel/src/integration.c index 8a3c581e..3d8258c1 100644 --- a/libcrystfel/src/integration.c +++ b/libcrystfel/src/integration.c @@ -1687,14 +1687,9 @@ void integrate_all_5(struct image *image, IntegrationMethod meth, saved_R * 5); } - if ( image->indexed_by != INDEXING_FILE ){ - res = estimate_resolution(crystal_get_cell(image->crystals[i]), + res = estimate_resolution(crystal_get_cell(image->crystals[i]), image->features); - crystal_set_resolution_limit(image->crystals[i], res); - } - else{ - res = crystal_get_resolution_limit(image->crystals[i]); - } + crystal_set_resolution_limit(image->crystals[i], res); list = predict_to_res(image->crystals[i], res+push_res); crystal_set_reflections(image->crystals[i], list); -- cgit v1.2.3