/* * facetron.c * * Profile fitting for coherent nanocrystallography * * (c) 2006-2010 Thomas White * * Part of CrystFEL - crystallography with a FEL * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include "utils.h" #include "hdf5-file.h" #include "symmetry.h" #include "reflections.h" #include "stream.h" #include "geometry.h" #define MAX_THREADS (256) struct process_args { struct image *image; /* Thread control */ pthread_mutex_t control_mutex; /* Protects the scary stuff below */ int start; int finish; int done; /* Analysis parameters */ const char *sym; ReflItemList *obs; double *i_full; }; static void show_help(const char *s) { printf("Syntax: %s [options]\n\n", s); printf( "Post-refinement and profile fitting for coherent nanocrystallography.\n" "\n" " -h, --help Display this help message.\n" "\n" " -i, --input= Specify the name of the input 'stream'.\n" " (must be a file, not e.g. stdin)\n" " -o, --output= Output filename. Default: facetron.hkl.\n" " -g. --geometry= Get detector geometry from file.\n" " -x, --prefix=

Prefix filenames from input file with

.\n" " --basename Remove the directory parts of the filenames.\n" " --no-check-prefix Don't attempt to correct the --prefix.\n" " -y, --symmetry= Merge according to symmetry .\n" " -n, --iterations= Run cycles of post-refinement.\n" "\n" " -j Run analyses in parallel.\n"); } static void refine_image(struct image *image, ReflItemList *obs, double *i_full) { //struct hdfile *hdfile; image->features = NULL; image->data = NULL; image->flags = NULL; image->hits = NULL; image->n_hits = 0; /* View head-on (unit cell is tilted) */ image->orientation.w = 1.0; image->orientation.x = 0.0; image->orientation.y = 0.0; image->orientation.z = 0.0; //hdfile = hdfile_open(pargs->filename); //if ( hdfile == NULL ) { // return; //} else if ( hdfile_set_first_image(hdfile, "/") ) { // ERROR("Couldn't select path\n"); // hdfile_close(hdfile); // return; //} //hdf5_read(hdfile, &image, 1); free(image->data); if ( image->flags != NULL ) free(image->flags); //hdfile_close(hdfile); } static void *worker_thread(void *pargsv) { struct process_args *pargs = pargsv; int finish; do { int wakeup; refine_image(pargs->image, pargs->obs, pargs->i_full); pthread_mutex_lock(&pargs->control_mutex); pargs->done = 1; pthread_mutex_unlock(&pargs->control_mutex); /* Go to sleep until told to exit or process next image */ do { pthread_mutex_lock(&pargs->control_mutex); /* Either of these can result in the thread waking up */ wakeup = pargs->start || pargs->finish; finish = pargs->finish; pthread_mutex_unlock(&pargs->control_mutex); usleep(20000); } while ( !wakeup ); } while ( !pargs->finish ); return NULL; } static void refine_all(struct image *images, int n_total_patterns, struct detector *det, const char *sym, ReflItemList *obs, double *i_full, int nthreads) { pthread_t workers[MAX_THREADS]; struct process_args *worker_args[MAX_THREADS]; int worker_active[MAX_THREADS]; int i; int n_done = 0; int n_started = 0; /* Initialise worker arguments with the unchanging data */ for ( i=0; icontrol_mutex, NULL); worker_args[i]->sym = sym; } /* Start threads off */ for ( i=0; iimage = &images[n_started++]; pthread_mutex_lock(&pargs->control_mutex); pargs->done = 0; pargs->start = 1; pargs->finish = 0; pthread_mutex_unlock(&pargs->control_mutex); worker_active[i] = 1; r = pthread_create(&workers[i], NULL, worker_thread, pargs); if ( r != 0 ) { worker_active[i] = 0; ERROR("Couldn't start thread %i\n", i); } } /* Keep threads busy until the end of the data */ do { int i; for ( i=0; icontrol_mutex); done = pargs->done; pthread_mutex_unlock(&pargs->control_mutex); if ( !done ) continue; /* Reset "done" flag */ pargs->done = 0; n_done++; progress_bar(n_done, n_total_patterns, "Refining"); /* If there are no more patterns, "done" will remain * zero, so the last pattern will not be re-counted. */ if ( n_started == n_total_patterns ) break; /* Start work on the next pattern */ pargs->image = &images[n_started++]; pthread_mutex_lock(&pargs->control_mutex); pargs->start = 1; pthread_mutex_unlock(&pargs->control_mutex); } } while ( n_started < n_total_patterns ); /* Join threads */ for ( i=0; icontrol_mutex); pargs->finish = 1; pthread_mutex_unlock(&pargs->control_mutex); /* Wait for it to join */ pthread_join(workers[i], NULL); if ( pargs->done ) { n_done++; progress_bar(n_done, n_total_patterns, "Refining"); } /* else this thread was not busy */ } } static double partiality(struct image *image, double x, double y) { return 1.0; } static void estimate_full(struct image *images, int n_total_patterns, struct detector *det, const char *sym, ReflItemList *obs, double *i_full) { int i; for ( i=0; iindexed_cell, image->div, image->bw, &n, 0); /* For each spot, estimate the partiality */ for ( j=0; j