aboutsummaryrefslogtreecommitdiff
path: root/src/partial_sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/partial_sim.c')
-rw-r--r--src/partial_sim.c1034
1 files changed, 0 insertions, 1034 deletions
diff --git a/src/partial_sim.c b/src/partial_sim.c
deleted file mode 100644
index f5588ceb..00000000
--- a/src/partial_sim.c
+++ /dev/null
@@ -1,1034 +0,0 @@
-/*
- * partial_sim.c
- *
- * Generate partials for testing scaling
- *
- * Copyright © 2012-2021 Deutsches Elektronen-Synchrotron DESY,
- * a research centre of the Helmholtz Association.
- *
- * Authors:
- * 2011-2020 Thomas White <taw@physics.org>
- * 2014 Valerio Mariani
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <assert.h>
-#include <pthread.h>
-#include <gsl/gsl_rng.h>
-
-#include <image.h>
-#include <utils.h>
-#include <reflist-utils.h>
-#include <symmetry.h>
-#include <geometry.h>
-#include <stream.h>
-#include <thread-pool.h>
-#include <cell-utils.h>
-
-#include "version.h"
-
-
-/* Number of bins for partiality graph */
-#define NBINS 50
-
-
-static void mess_up_cell(Crystal *cr, double cnoise, gsl_rng *rng)
-{
- double ax, ay, az;
- double bx, by, bz;
- double cx, cy, cz;
- UnitCell *cell = crystal_get_cell(cr);
-
- //STATUS("Real:\n");
- //cell_print(cell);
-
- cell_get_reciprocal(cell, &ax, &ay, &az, &bx, &by, &bz, &cx, &cy, &cz);
- ax = flat_noise(rng, ax, cnoise*fabs(ax)/100.0);
- ay = flat_noise(rng, ay, cnoise*fabs(ay)/100.0);
- az = flat_noise(rng, az, cnoise*fabs(az)/100.0);
- bx = flat_noise(rng, bx, cnoise*fabs(bx)/100.0);
- by = flat_noise(rng, by, cnoise*fabs(by)/100.0);
- bz = flat_noise(rng, bz, cnoise*fabs(bz)/100.0);
- cx = flat_noise(rng, cx, cnoise*fabs(cx)/100.0);
- cy = flat_noise(rng, cy, cnoise*fabs(cy)/100.0);
- cz = flat_noise(rng, cz, cnoise*fabs(cz)/100.0);
- cell_set_reciprocal(cell, ax, ay, az, bx, by, bz, cx, cy, cz);
-
- //STATUS("Changed:\n");
- //cell_print(cell);
-}
-
-
-/* For each reflection in "partial", fill in what the intensity would be
- * according to "full" */
-static void calculate_partials(Crystal *cr,
- RefList *full, const SymOpList *sym,
- int random_intensities,
- pthread_rwlock_t *full_lock,
- unsigned long int *n_ref, double *p_hist,
- double *p_max, double max_q, double full_stddev,
- double noise_stddev, gsl_rng *rng,
- UnitCell *template_cell, RefList *template_reflist)
-{
- Reflection *refl;
- RefListIterator *iter;
-
- for ( refl = first_refl(crystal_get_reflections(cr), &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- signed int h, k, l;
- Reflection *rfull;
- double L, p, Ip, If;
- int bin;
- double res;
-
- get_indices(refl, &h, &k, &l);
- get_asymm(sym, h, k, l, &h, &k, &l);
- p = get_partiality(refl);
- L = get_lorentz(refl);
-
- pthread_rwlock_rdlock(full_lock);
- rfull = find_refl(full, h, k, l);
- pthread_rwlock_unlock(full_lock);
-
- if ( rfull == NULL ) {
- if ( random_intensities ) {
-
- pthread_rwlock_wrlock(full_lock);
-
- /* In the gap between the unlock and the wrlock,
- * the reflection might have been created by
- * another thread. So, we must check again */
- rfull = find_refl(full, h, k, l);
- if ( rfull == NULL ) {
- rfull = add_refl(full, h, k, l);
- If = fabs(gaussian_noise(rng, 0.0,
- full_stddev));
- set_intensity(rfull, If);
- set_redundancy(rfull, 1);
- } else {
- If = get_intensity(rfull);
- }
- pthread_rwlock_unlock(full_lock);
-
- } else {
- set_redundancy(refl, 0);
- If = 0.0;
- }
- } else {
- If = get_intensity(rfull);
- if ( random_intensities ) {
- lock_reflection(rfull);
- int red = get_redundancy(rfull);
- set_redundancy(rfull, red+1);
- unlock_reflection(rfull);
- }
- }
-
- Ip = crystal_get_osf(cr) * L * p * If;
-
- res = resolution(crystal_get_cell(cr), h, k, l);
- bin = NBINS*2.0*res/max_q;
- if ( (bin < NBINS) && (bin>=0) ) {
- p_hist[bin] += p;
- n_ref[bin]++;
- if ( p > p_max[bin] ) p_max[bin] = p;
- } else {
- STATUS("Reflection out of histogram range: %e %i %f\n",
- res, bin, p);
- }
-
- Ip = gaussian_noise(rng, Ip, noise_stddev);
-
- set_intensity(refl, Ip);
- set_esd_intensity(refl, noise_stddev);
- }
-}
-
-
-static void draw_and_write_image(struct image *image,
- const DataTemplate *dtempl,
- RefList *reflections,
- gsl_rng *rng, double background)
-{
- Reflection *refl;
- RefListIterator *iter;
- int i;
-
- image->dp = malloc(image->detgeom->n_panels*sizeof(float *));
- if ( image->dp == NULL ) {
- ERROR("Failed to allocate data\n");
- return;
- }
- for ( i=0; i<image->detgeom->n_panels; i++ ) {
-
- int j;
- struct detgeom_panel *p = &image->detgeom->panels[i];
-
- image->dp[i] = calloc(p->w * p->h, sizeof(float));
- if ( image->dp[i] == NULL ) {
- ERROR("Failed to allocate data\n");
- return;
- }
- for ( j=0; j<p->w*p->h; j++ ) {
- image->dp[i][j] = poisson_noise(rng, background);
- }
-
- }
-
- for ( refl = first_refl(reflections, &iter);
- refl != NULL;
- refl = next_refl(refl, iter) )
- {
- double Ip;
- double dfs, dss;
- int fs, ss;
- struct detgeom_panel *p;
- signed int pn;
-
- Ip = get_intensity(refl);
-
- get_detector_pos(refl, &dfs, &dss);
- pn = get_panel_number(refl);
- assert(pn < image->detgeom->n_panels);
- p = &image->detgeom->panels[pn];
-
- /* Explicit rounding, downwards */
- fs = dfs; ss = dss;
- assert(fs >= 0);
- assert(ss >= 0);
- assert(fs < p->w);
- assert(ss < p->h);
-
- image->dp[pn][fs + p->w*ss] += Ip;
- }
-
- image_write(image, dtempl, image->filename);
-
- for ( i=0; i<image->detgeom->n_panels; i++ ) {
- free(image->dp[i]);
- }
- free(image->dp);
-}
-
-
-static void show_help(const char *s)
-{
- printf("Syntax: %s [options]\n\n", s);
- printf(
-"Generate a stream containing partials from a reflection list.\n"
-"\n"
-" -h, --help Display this help message.\n"
-" --version Print CrystFEL version number and exit.\n"
-"\n"
-"You need to provide the following basic options:\n"
-" -i, --input=<file> Read reflections from <file>.\n"
-" Default: generate random ones instead (see -r).\n"
-" -o, --output=<file> Write partials in stream format to <file>.\n"
-" --images=<prefix> Write images to <prefix>NNN.h5.\n"
-" -g. --geometry=<file> Get detector geometry from file.\n"
-" -p, --pdb=<file> PDB file from which to get the unit cell.\n"
-"\n"
-" -y, --symmetry=<sym> Symmetry of the input reflection list.\n"
-" -n <n> Simulate <n> patterns. Default: 2.\n"
-" -r, --save-random=<file> Save randomly generated intensities to file.\n"
-" --pgraph=<file> Save a histogram of partiality values to file.\n"
-" -c, --cnoise=<val> Amount of reciprocal space cell noise, in percent.\n"
-" --osf-stddev=<val> Standard deviation of the scaling factors.\n"
-" --full-stddev=<val> Standard deviation of the randomly\n"
-" generated full intensities, if not using -i.\n"
-" --noise-stddev=<val> Set the standard deviation of the noise.\n"
-" --background=<val> Background level in photons. Default 3000.\n"
-" --profile-radius Reciprocal space reflection profile radius in m^-1.\n"
-" Default 0.001e9 m^-1\n"
-" --really-random Be non-deterministic.\n"
-"\n"
-);
-}
-
-
-struct partial_sim_queue_args
-{
- RefList *full;
- pthread_rwlock_t full_lock;
- const DataTemplate *dtempl;
-
- int n_done;
- int n_started;
- int n_to_do;
-
- SymOpList *sym;
- int random_intensities;
- UnitCell *cell;
- double cnoise;
- double osf_stddev;
- double full_stddev;
- double noise_stddev;
- double background;
- double profile_radius;
-
- double max_q;
-
- char *image_prefix;
-
- /* The overall histogram */
- double p_hist[NBINS];
- unsigned long int n_ref[NBINS];
- double p_max[NBINS];
-
- Stream *stream;
- gsl_rng **rngs;
- Stream *template_stream;
-};
-
-
-struct partial_sim_worker_args
-{
- struct partial_sim_queue_args *qargs;
- struct image *image;
-
- UnitCell *template_cell;
- RefList *template_reflist;
-
- /* Histogram for this image */
- double p_hist[NBINS];
- unsigned long int n_ref[NBINS];
- double p_max[NBINS];
-
- int n;
-};
-
-
-static void *create_job(void *vqargs)
-{
- struct partial_sim_worker_args *wargs;
- struct partial_sim_queue_args *qargs = vqargs;
-
- /* All done already? */
- if ( qargs->n_started == qargs->n_to_do ) return NULL;
-
- wargs = malloc(sizeof(struct partial_sim_worker_args));
-
- wargs->qargs = qargs;
-
- if ( qargs->template_stream != NULL ) {
-
- struct image *image;
-
- image = stream_read_chunk(qargs->template_stream,
- STREAM_REFLECTIONS);
- if ( image == NULL ) {
- ERROR("Failed to read template chunk!\n");
- free(wargs);
- return NULL;
- }
- if ( image->n_crystals != 1 ) {
- ERROR("Template stream must have exactly one crystal "
- "per frame.\n");
- free(wargs);
- return NULL;
- }
-
- wargs->template_cell = crystal_get_cell(image->crystals[0]);
- wargs->template_reflist = crystal_get_reflections(image->crystals[0]);
-
- image_free(image);
-
- } else {
- wargs->template_cell = NULL;
- wargs->template_reflist = NULL;
- }
-
- qargs->n_started++;
- wargs->n = qargs->n_started;
-
- return wargs;
-}
-
-
-static void run_job(void *vwargs, int cookie)
-{
- struct partial_sim_worker_args *wargs = vwargs;
- struct partial_sim_queue_args *qargs = wargs->qargs;
- int i;
- Crystal *cr;
- double osf;
- struct image *image;
-
- image = image_create_for_simulation(qargs->dtempl);
- if ( image == NULL ) {
- ERROR("Failed to create image.\n");
- return;
- }
-
- cr = crystal_new();
- if ( cr == NULL ) {
- ERROR("Failed to create crystal.\n");
- return;
- }
- crystal_set_image(cr, image);
- image_add_crystal(image, cr);
-
- do {
- osf = gaussian_noise(qargs->rngs[cookie], 1.0,
- qargs->osf_stddev);
- } while ( osf <= 0.0 );
- crystal_set_osf(cr, osf);
- crystal_set_mosaicity(cr, 0.0);
- crystal_set_profile_radius(cr, qargs->profile_radius);
-
- if ( wargs->template_cell == NULL ) {
- /* Set up a random orientation */
- struct quaternion orientation;
- char tmp[128];
- orientation = random_quaternion(qargs->rngs[cookie]);
- crystal_set_cell(cr, cell_rotate(qargs->cell, orientation));
- snprintf(tmp, 127, "quaternion = %f %f %f %f",
- orientation.w, orientation.x, orientation.y, orientation.z);
- crystal_add_notes(cr, tmp);
- } else {
- crystal_set_cell(cr, wargs->template_cell);
- }
-
- image->filename = malloc(256);
- if ( image->filename == NULL ) {
- ERROR("Failed to allocate filename.\n");
- return;
- }
- if ( qargs->image_prefix != NULL ) {
- snprintf(image->filename, 255, "%s%i.h5",
- qargs->image_prefix, wargs->n);
- } else {
- snprintf(image->filename, 255, "dummy-%i.h5", wargs->n);
- }
-
- if ( wargs->template_reflist == NULL ) {
- RefList *reflections;
- reflections = predict_to_res(cr, qargs->max_q);
- crystal_set_reflections(cr, reflections);
- calculate_partialities(cr, PMODEL_XSPHERE);
- } else {
- crystal_set_reflections(cr, wargs->template_reflist);
- update_predictions(cr);
- calculate_partialities(cr, PMODEL_XSPHERE);
- }
-
- for ( i=0; i<NBINS; i++ ) {
- wargs->n_ref[i] = 0;
- wargs->p_hist[i] = 0.0;
- wargs->p_max[i] = 0.0;
- }
-
- calculate_partials(cr, qargs->full,
- qargs->sym, qargs->random_intensities,
- &qargs->full_lock,
- wargs->n_ref, wargs->p_hist, wargs->p_max,
- qargs->max_q, qargs->full_stddev,
- qargs->noise_stddev, qargs->rngs[cookie],
- wargs->template_cell, wargs->template_reflist);
-
- if ( qargs->image_prefix != NULL ) {
- draw_and_write_image(image, qargs->dtempl,
- crystal_get_reflections(cr),
- qargs->rngs[cookie],
- qargs->background);
- }
-
- /* Give a slightly incorrect cell in the stream */
- mess_up_cell(cr, qargs->cnoise, qargs->rngs[cookie]);
-
- wargs->image = image;
-}
-
-
-static void finalise_job(void *vqargs, void *vwargs)
-{
- struct partial_sim_worker_args *wargs = vwargs;
- struct partial_sim_queue_args *qargs = vqargs;
- int i;
- int ret;
-
- ret = stream_write_chunk(qargs->stream, wargs->image,
- STREAM_REFLECTIONS);
- if ( ret != 0 ) {
- ERROR("WARNING: error writing stream file.\n");
- }
-
- for ( i=0; i<NBINS; i++ ) {
- qargs->n_ref[i] += wargs->n_ref[i];
- qargs->p_hist[i] += wargs->p_hist[i];
- if ( wargs->p_max[i] > qargs->p_max[i] ) {
- qargs->p_max[i] = wargs->p_max[i];
- }
- }
-
- qargs->n_done++;
- progress_bar(qargs->n_done, qargs->n_to_do, "Simulating");
-
- image_free(wargs->image);
-}
-
-
-int main(int argc, char *argv[])
-{
- int c;
- char *input_file = NULL;
- char *output_file = NULL;
- char *geomfile = NULL;
- char *cellfile = NULL;
- DataTemplate *dtempl;
- RefList *full = NULL;
- char *sym_str = NULL;
- SymOpList *sym;
- UnitCell *cell = NULL;
- Stream *stream;
- int n = 2;
- int random_intensities = 0;
- char *save_file = NULL;
- struct partial_sim_queue_args qargs;
- int n_threads = 1;
- char *rval;
- int i;
- char *phist_file = NULL;
- int config_random = 0;
- char *image_prefix = NULL;
- Stream *template_stream = NULL;
- char *template = NULL;
- struct image *test_image;
-
- /* Default simulation parameters */
- double profile_radius = 0.001e9;
- double osf_stddev = 2.0;
- double full_stddev = 1000.0;
- double noise_stddev = 20.0;
- double background = 3000.0;
- double cnoise = 0.0;
-
- /* Long options */
- const struct option longopts[] = {
- {"help", 0, NULL, 'h'},
- {"version", 0, NULL, 'v'},
- {"beam", 1, NULL, 'b'},
- {"output", 1, NULL, 'o'},
- {"input", 1, NULL, 'i'},
- {"pdb", 1, NULL, 'p'},
- {"geometry", 1, NULL, 'g'},
- {"symmetry", 1, NULL, 'y'},
- {"save-random", 1, NULL, 'r'},
- {"cnoise", 1, NULL, 'c'},
-
- {"pgraph", 1, NULL, 2},
- {"osf-stddev", 1, NULL, 3},
- {"full-stddev", 1, NULL, 4},
- {"noise-stddev", 1, NULL, 5},
- {"images", 1, NULL, 6},
- {"background", 1, NULL, 7},
- {"beam-divergence", 1, NULL, 8},
- {"beam-bandwidth", 1, NULL, 9},
- {"profile-radius", 1, NULL, 10},
- {"photon-energy", 1, NULL, 11},
- {"template-stream", 1, NULL, 12},
-
- {"really-random", 0, &config_random, 1},
-
- {0, 0, NULL, 0}
- };
-
- /* Short options */
- while ((c = getopt_long(argc, argv, "hi:o:p:g:y:n:r:j:c:vb:",
- longopts, NULL)) != -1)
- {
- switch (c) {
-
- case 'h' :
- show_help(argv[0]);
- return 0;
-
- case 'v' :
- printf("CrystFEL: %s\n",
- crystfel_version_string());
- printf("%s\n",
- crystfel_licence_string());
- return 0;
-
- case 'b' :
- ERROR("WARNING: This version of CrystFEL no longer "
- "uses beam files. Please remove the beam file "
- "from your partial_sim command line.\n");
- return 1;
-
- case 'i' :
- input_file = strdup(optarg);
- break;
-
- case 'o' :
- output_file = strdup(optarg);
- break;
-
- case 'p' :
- cellfile = strdup(optarg);
- break;
-
- case 'g' :
- geomfile = strdup(optarg);
- break;
-
- case 'y' :
- sym_str = strdup(optarg);
- break;
-
- case 'n' :
- n = atoi(optarg);
- break;
-
- case 'r' :
- save_file = strdup(optarg);
- break;
-
- case 'j' :
- n_threads = atoi(optarg);
- break;
-
- case 'c' :
- cnoise = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid cell noise value.\n");
- return 1;
- }
- break;
-
- case 2 :
- phist_file = strdup(optarg);
- break;
-
- case 3 :
- osf_stddev = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid OSF standard deviation.\n");
- return 1;
- }
- if ( osf_stddev < 0.0 ) {
- ERROR("Invalid OSF standard deviation.");
- ERROR(" (must be positive).\n");
- return 1;
- }
- break;
-
- case 4 :
- full_stddev = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid full standard deviation.\n");
- return 1;
- }
- if ( full_stddev < 0.0 ) {
- ERROR("Invalid full standard deviation.");
- ERROR(" (must be positive).\n");
- return 1;
- }
- break;
-
- case 5 :
- noise_stddev = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid noise standard deviation.\n");
- return 1;
- }
- if ( noise_stddev < 0.0 ) {
- ERROR("Invalid noise standard deviation.");
- ERROR(" (must be positive).\n");
- return 1;
- }
- break;
-
- case 6 :
- image_prefix = strdup(optarg);
- break;
-
- case 7 :
- background = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid background level.\n");
- return 1;
- }
- if ( background < 0.0 ) {
- ERROR("Background level must be positive.\n");
- return 1;
- }
- break;
-
- case 8 :
- ERROR("--beam-divergence is no longer used.\n");
- ERROR("The 'xsphere' partiality model does not take divergence into account.\n");
- return 1;
-
- case 9 :
- ERROR("--beam-bandwidth is no longer used.\n");
- ERROR("Set the bandwidth in the geometry file instead.\n");
- return 1;
-
- case 10 :
- profile_radius = strtod(optarg, &rval);
- if ( *rval != '\0' ) {
- ERROR("Invalid profile radius.\n");
- return 1;
- }
- if ( profile_radius < 0.0 ) {
- ERROR("Profile radius must be positive.\n");
- return 1;
- }
- break;
-
- case 11 :
- ERROR("--photon-energy is no longer used.\n");
- ERROR("Set the photon energy in the geometry file instead.\n");
- return 1;
-
- case 12 :
- template = strdup(optarg);
- break;
-
- case 0 :
- break;
-
- case '?' :
- return 1;
-
- default :
- ERROR("Unhandled option '%c'\n", c);
- break;
-
- }
- }
-
- if ( n_threads < 1 ) {
- ERROR("Invalid number of threads.\n");
- return 1;
- }
-
- if ( (n_threads > 1) && (image_prefix != NULL) ) {
- ERROR("Option \"--images\" is incompatible with \"-j\".\n");
- return 1;
- }
-
- /* Load cell */
- if ( cellfile == NULL ) {
- ERROR("You need to give a PDB file with the unit cell.\n");
- return 1;
- }
- cell = load_cell_from_file(cellfile);
- if ( cell == NULL ) {
- ERROR("Failed to get cell from '%s'\n", cellfile);
- return 1;
- }
- free(cellfile);
-
- if ( !cell_is_sensible(cell) ) {
- ERROR("Invalid unit cell parameters:\n");
- cell_print(cell);
- return 1;
- }
-
- /* Load geometry */
- if ( geomfile == NULL ) {
- ERROR("You need to give a geometry file.\n");
- return 1;
- }
- dtempl = data_template_new_from_file(geomfile);
- if ( dtempl == NULL ) {
- ERROR("Failed to read geometry from '%s'\n", geomfile);
- return 1;
- }
-
- if ( save_file == NULL ) save_file = strdup("partial_sim.hkl");
-
- /* Load (full) reflections */
- if ( input_file != NULL ) {
-
- RefList *as;
- char *sym_str_fromfile = NULL;
-
- full = read_reflections_2(input_file, &sym_str_fromfile);
- if ( full == NULL ) {
- ERROR("Failed to read reflections from '%s'\n",
- input_file);
- return 1;
- }
-
- /* If we don't have a point group yet, and if the file provides
- * one, use the one from the file */
- if ( (sym_str == NULL) && (sym_str_fromfile != NULL) ) {
- sym_str = sym_str_fromfile;
- STATUS("Using symmetry from reflection file: %s\n",
- sym_str);
- }
-
- /* If we still don't have a point group, use "1" */
- if ( sym_str == NULL ) sym_str = strdup("1");
-
- pointgroup_warning(sym_str);
- sym = get_pointgroup(sym_str);
-
- if ( check_list_symmetry(full, sym) ) {
- ERROR("The input reflection list does not appear to"
- " have symmetry %s\n", symmetry_name(sym));
- if ( cell_get_lattice_type(cell) == L_MONOCLINIC ) {
- ERROR("You may need to specify the unique axis "
- "in your point group. The default is "
- "unique axis c.\n");
- ERROR("See 'man crystfel' for more details.\n");
- }
- return 1;
- }
-
- as = asymmetric_indices(full, sym);
- reflist_free(full);
- full = as;
-
- } else {
- random_intensities = 1;
- if ( sym_str == NULL ) sym_str = strdup("1");
- sym = get_pointgroup(sym_str);
- }
-
- if ( n < 1 ) {
- ERROR("Number of patterns must be at least 1.\n");
- return 1;
- }
-
- if ( output_file == NULL ) {
- ERROR("You must give a filename for the output.\n");
- return 1;
- }
- stream = stream_open_for_write(output_file, dtempl);
- if ( stream == NULL ) {
- ERROR("Couldn't open output file '%s'\n", output_file);
- return 1;
- }
- free(output_file);
-
- stream_write_geometry_file(stream, geomfile);
- stream_write_commandline_args(stream, argc, argv);
-
- if ( template != NULL ) {
- template_stream = stream_open_for_read(template);
- if ( template_stream == NULL ) {
- ERROR("Couldn't open template stream '%s'\n", template);
- return 1;
- }
- }
-
- test_image = image_create_for_simulation(dtempl);
- if ( test_image == NULL ) {
- ERROR("Could not create image structure.\n");
- ERROR("Does the geometry file contain references?\n");
- return 1;
- }
-
- STATUS("Simulation parameters:\n");
- STATUS(" Wavelength: %.5f A (photon energy %.2f eV)\n",
- test_image->lambda*1e10,
- ph_lambda_to_eV(test_image->lambda));
- STATUS(" Beam divergence: 0 (not modelled)\n");
- STATUS(" Beam bandwidth: %.5f %%\n",
- test_image->bw*100.0);
- STATUS("Reciprocal space profile radius: %e m^-1\n",
- profile_radius);
- if ( image_prefix != NULL ) {
- STATUS(" Background: %.2f detector units\n",
- background);
- } else {
- STATUS(" Background: none (no image "
- "output)\n");
- }
- STATUS(" Partiality model: xsphere (hardcoded)\n");
- STATUS(" Noise standard deviation: %.2f detector units\n",
- noise_stddev);
- if ( random_intensities ) {
- STATUS(" Full intensities: randomly generated: "
- "abs(Gaussian(sigma=%.2f)), symmetry %s\n",
- full_stddev, sym_str);
- } else {
- STATUS(" Full intensities: from %s (symmetry %s)\n",
- input_file, sym_str);
- }
- STATUS(" Max error in cell components: %.2f %%\n", cnoise);
- STATUS("Scale factor standard deviation: %.2f\n", osf_stddev);
- if ( template_stream != NULL ) {
- STATUS("Crystal orientations and reflections to use from %s\n",
- template);
- }
-
- if ( random_intensities ) {
- full = reflist_new();
- }
-
- qargs.full = full;
- pthread_rwlock_init(&qargs.full_lock, NULL);
- qargs.n_to_do = n;
- qargs.n_done = 0;
- qargs.n_started = 0;
- qargs.sym = sym;
- qargs.dtempl = dtempl;
- qargs.random_intensities = random_intensities;
- qargs.cell = cell;
- qargs.stream = stream;
- qargs.cnoise = cnoise;
- qargs.osf_stddev = osf_stddev;
- qargs.full_stddev = full_stddev;
- qargs.noise_stddev = noise_stddev;
- qargs.background = background;
- qargs.max_q = detgeom_max_resolution(test_image->detgeom,
- test_image->lambda);
- qargs.image_prefix = image_prefix;
- qargs.profile_radius = profile_radius;
- qargs.template_stream = template_stream;
-
- qargs.rngs = malloc(n_threads * sizeof(gsl_rng *));
- if ( qargs.rngs == NULL ) {
- ERROR("Failed to allocate RNGs\n");
- return 1;
- }
-
- if ( config_random ) {
-
- FILE *fh;
-
- fh = fopen("/dev/urandom", "r");
- if ( fh == NULL ) {
- ERROR("Failed to open /dev/urandom. Try again without"
- " --really-random.\n");
- free(qargs.rngs);
- return 1;
- }
-
- for ( i=0; i<n_threads; i++ ) {
-
- unsigned long int seed;
- qargs.rngs[i] = gsl_rng_alloc(gsl_rng_mt19937);
-
- if ( fread(&seed, sizeof(seed), 1, fh) == 1 ) {
- gsl_rng_set(qargs.rngs[i], seed);
- } else {
- ERROR("Failed to seed RNG %i\n", i);
- }
-
- }
-
- fclose(fh);
-
- } else {
- gsl_rng *rng_for_seeds;
- rng_for_seeds = gsl_rng_alloc(gsl_rng_mt19937);
- for ( i=0; i<n_threads; i++ ) {
- qargs.rngs[i] = gsl_rng_alloc(gsl_rng_mt19937);
- gsl_rng_set(qargs.rngs[i], gsl_rng_get(rng_for_seeds));
- }
- gsl_rng_free(rng_for_seeds);
- }
-
- for ( i=0; i<NBINS; i++ ) {
- qargs.n_ref[i] = 0;
- qargs.p_hist[i] = 0.0;
- qargs.p_max[i] = 0.0;
- }
-
- run_threads(n_threads, run_job, create_job, finalise_job,
- &qargs, n, 0, 0, 0);
-
- if ( random_intensities ) {
- STATUS("Writing full intensities to %s\n", save_file);
- write_reflist_2(save_file, full, sym);
- }
-
- if ( phist_file != NULL ) {
-
- FILE *fh;
-
- fh = fopen(phist_file, "w");
-
- if ( fh != NULL ) {
-
- double overall_max = 0.0;
- double overall_mean = 0.0;
- long long int overall_total = 0;
-
- for ( i=0; i<NBINS; i++ ) {
-
- double rcen;
-
- if ( qargs.p_max[i] > overall_max ) {
- overall_max = qargs.p_max[i];
- }
-
- overall_mean += qargs.p_hist[i];
- overall_total += qargs.n_ref[i];
-
- rcen = i/(double)NBINS*qargs.max_q
- + qargs.max_q/(2.0*NBINS);
- fprintf(fh, "%.2f %7lu %.3f %.3f\n", rcen/1.0e9,
- qargs.n_ref[i],
- qargs.p_hist[i]/qargs.n_ref[i],
- qargs.p_max[i]);
-
- }
-
- fclose(fh);
-
- overall_mean /= overall_total;
-
- STATUS("Overall max partiality = %.2f\n",
- overall_max);
- STATUS("Overall mean partiality = %.2f\n", overall_mean);
- STATUS("Total number of reflections = %lli\n",
- overall_total);
-
- } else {
- ERROR("Failed to open file '%s' for writing.\n",
- phist_file);
- }
-
- }
-
- for ( i=0; i<n_threads; i++ ) {
- gsl_rng_free(qargs.rngs[i]);
- }
- free(qargs.rngs);
- pthread_rwlock_destroy(&qargs.full_lock);
- stream_close(stream);
- cell_free(cell);
- data_template_free(dtempl);
- free_symoplist(sym);
- reflist_free(full);
- free(save_file);
- free(geomfile);
- free(input_file);
-
- return 0;
-}