/* * partialator.c * * Scaling and post refinement for coherent nanocrystallography * * (c) 2006-2011 Thomas White * * Part of CrystFEL - crystallography with a FEL * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "utils.h" #include "hdf5-file.h" #include "symmetry.h" #include "stream.h" #include "geometry.h" #include "peaks.h" #include "thread-pool.h" #include "beam-parameters.h" #include "post-refinement.h" #include "hrs-scaling.h" #include "reflist.h" #include "reflist-utils.h" static void show_help(const char *s) { printf("Syntax: %s [options]\n\n", s); printf( "Scaling and post refinement 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" " -b, --beam= Get beam parameters from file, which provides\n" " initial values for parameters, and nominal\n" " wavelengths if no per-shot value is found in \n" " an HDF5 file.\n" " -y, --symmetry= Merge according to symmetry .\n" " -n, --iterations= Run cycles of scaling and post-refinement.\n" "\n" " -j Run analyses in parallel.\n"); } struct refine_args { const char *sym; ReflItemList *obs; RefList *full; struct image *image; FILE *graph; FILE *pgraph; }; struct queue_args { int n; int n_done; int n_total_patterns; struct image *images; struct refine_args task_defaults; }; static void refine_image(void *task, int id) { struct refine_args *pargs = task; struct image *image = pargs->image; image->id = id; pr_refine(image, pargs->full, pargs->sym); } static void *get_image(void *vqargs) { struct refine_args *task; struct queue_args *qargs = vqargs; task = malloc(sizeof(struct refine_args)); memcpy(task, &qargs->task_defaults, sizeof(struct refine_args)); task->image = &qargs->images[qargs->n]; qargs->n++; return task; } static void done_image(void *vqargs, void *task) { struct queue_args *qargs = vqargs; qargs->n_done++; progress_bar(qargs->n_done, qargs->n_total_patterns, "Refining"); free(task); } static void refine_all(struct image *images, int n_total_patterns, struct detector *det, const char *sym, ReflItemList *obs, RefList *full, int nthreads, FILE *graph, FILE *pgraph) { struct refine_args task_defaults; struct queue_args qargs; task_defaults.sym = sym; task_defaults.obs = obs; task_defaults.full = full; task_defaults.image = NULL; task_defaults.graph = graph; task_defaults.pgraph = pgraph; qargs.task_defaults = task_defaults; qargs.n = 0; qargs.n_done = 0; /* FIXME: Not refining the first image, for now */ qargs.n_total_patterns = n_total_patterns-1; qargs.images = images+1; run_threads(nthreads, refine_image, get_image, done_image, &qargs, n_total_patterns-1, 0, 0, 0); } int main(int argc, char *argv[]) { int c; char *infile = NULL; char *outfile = NULL; char *geomfile = NULL; char *sym = NULL; FILE *fh; int nthreads = 1; struct detector *det; ReflItemList *obs; int i; int n_total_patterns; struct image *images; int n_iter = 10; struct beam_params *beam = NULL; RefList *full; int n_found = 0; int n_expected = 0; int n_notfound = 0; char *cref; int n_usable_patterns = 0; /* Long options */ const struct option longopts[] = { {"help", 0, NULL, 'h'}, {"input", 1, NULL, 'i'}, {"output", 1, NULL, 'o'}, {"geometry", 1, NULL, 'g'}, {"beam", 1, NULL, 'b'}, {"symmetry", 1, NULL, 'y'}, {"iterations", 1, NULL, 'n'}, {0, 0, NULL, 0} }; /* Short options */ while ((c = getopt_long(argc, argv, "hi:g:x:j:y:o:b:", longopts, NULL)) != -1) { switch (c) { case 'h' : show_help(argv[0]); return 0; case 'i' : infile = strdup(optarg); break; case 'g' : geomfile = strdup(optarg); break; case 'j' : nthreads = atoi(optarg); break; case 'y' : sym = strdup(optarg); break; case 'o' : outfile = strdup(optarg); break; case 'n' : n_iter = atoi(optarg); break; case 'b' : beam = get_beam_parameters(optarg); if ( beam == NULL ) { ERROR("Failed to load beam parameters" " from '%s'\n", optarg); return 1; } break; case 0 : break; default : return 1; } } /* Sanitise input filename and open */ if ( infile == NULL ) { infile = strdup("-"); } if ( strcmp(infile, "-") == 0 ) { fh = stdin; } else { fh = fopen(infile, "r"); } if ( fh == NULL ) { ERROR("Failed to open input file '%s'\n", infile); return 1; } free(infile); /* Sanitise output filename */ if ( outfile == NULL ) { outfile = strdup("partialator.hkl"); } if ( sym == NULL ) sym = strdup("1"); /* Get detector geometry */ det = get_detector_geometry(geomfile); if ( det == NULL ) { ERROR("Failed to read detector geometry from '%s'\n", geomfile); return 1; } free(geomfile); if ( beam == NULL ) { ERROR("You must provide a beam parameters file.\n"); return 1; } n_total_patterns = count_patterns(fh); if ( n_total_patterns == 0 ) { ERROR("No patterns to process.\n"); return 1; } STATUS("There are %i patterns to process\n", n_total_patterns); images = malloc(n_total_patterns * sizeof(struct image)); if ( images == NULL ) { ERROR("Couldn't allocate memory for images.\n"); return 1; } /* Fill in what we know about the images so far */ rewind(fh); obs = new_items(); for ( i=0; idivergence; images[n_usable_patterns].bw = beam->bandwidth; images[n_usable_patterns].det = det; images[n_usable_patterns].width = det->max_fs; images[n_usable_patterns].height = det->max_ss; images[n_usable_patterns].osf = 1.0; images[n_usable_patterns].profile_radius = 0.005e9; /* Muppet proofing */ images[n_usable_patterns].data = NULL; images[n_usable_patterns].flags = NULL; images[n_usable_patterns].beam = NULL; /* This is the raw list of reflections */ images[n_usable_patterns].raw_reflections = images[n_usable_patterns].reflections; images[n_usable_patterns].reflections = NULL; update_partialities_and_asymm(&images[n_usable_patterns], sym, obs, &n_expected, &n_found, &n_notfound); progress_bar(i, n_total_patterns-1, "Loading pattern data"); n_usable_patterns++; } fclose(fh); STATUS("Found %5.2f%% of the expected peaks (missed %i of %i).\n", 100.0 * (double)n_found / n_expected, n_notfound, n_expected); STATUS("Mean measurements per unique reflection: %5.2f\n", (double)n_found / num_items(obs)); cref = find_common_reflections(images, n_usable_patterns); /* Make initial estimates */ STATUS("Performing initial scaling.\n"); full = scale_intensities(images, n_usable_patterns, sym, obs, cref); /* Iterate */ for ( i=0; i