/* * get_hkl.c * * Small program to manipulate reflection lists * * Copyright © 2012 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * * Authors: * 2009-2012 Thomas White * * 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 . * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include "utils.h" #include "reflist-utils.h" #include "symmetry.h" #include "beam-parameters.h" static void show_help(const char *s) { printf("Syntax: %s [options]\n\n", s); printf( "Manipulate reflection lists.\n" "\n" " -h, --help Display this help message.\n" "\n" " -i, --input= Read reflections from .\n" " -y, --symmetry= The symmetry of the input reflection list.\n" "\n" "You can add noise to the reflections with either of:\n" " --poisson Simulate Poisson samples.\n" " --noise Add 10%% random noise.\n" "\n" "To calculate Poisson samples accurately, you must also give:\n" " --adu-per-photon= Number of ADU per photon.\n" "\n" "You can artificially 'twin' the reflections, or expand them out.\n" " -w, --twin= Generate twinned data according to the given\n" " point group.\n" " -e, --expand= Expand reflections to this point group.\n" "\n" "Use this option with care, and only if you understand why it might sometimes\n" " be necessary:\n" " --trim-centrics Remove reflections which are duplicated in the\n" " point group specified with the '-y' option.\n" "\n" "You can restrict which reflections are written out:\n" " -t, --template= Only include reflections mentioned in file.\n" "\n" "You might sometimes need to do this:\n" " --multiplicity Multiply intensities by the number of\n" " equivalent reflections.\n" "\n" "Don't forget to specify the output filename:\n" " -o, --output= Output filename (default: stdout).\n" ); } /* Apply Poisson noise to all reflections */ static void poisson_reflections(RefList *list, double adu_per_photon) { Reflection *refl; RefListIterator *iter; for ( refl = first_refl(list, &iter); refl != NULL; refl = next_refl(refl, iter) ) { double val, c; val = get_intensity(refl); c = adu_per_photon * poisson_noise(val/adu_per_photon); set_intensity(refl, c); } } /* Apply 10% uniform noise to all reflections */ static void noise_reflections(RefList *list) { Reflection *refl; RefListIterator *iter; for ( refl = first_refl(list, &iter); refl != NULL; refl = next_refl(refl, iter) ) { double val, r; val = get_intensity(refl); r = (double)random()/RAND_MAX; val += 0.1 * val * r; set_intensity(refl, val); } } static RefList *template_reflections(RefList *list, RefList *template) { Reflection *refl; RefListIterator *iter; RefList *out; out = reflist_new(); for ( refl = first_refl(template, &iter); refl != NULL; refl = next_refl(refl, iter) ) { signed int h, k, l; Reflection *new; Reflection *old; get_indices(refl, &h, &k, &l); old = find_refl(list, h, k, l); if ( old == NULL ) continue; new = add_refl(out, h, k, l); copy_data(new, old); } return out; } static RefList *twin_reflections(RefList *in, const SymOpList *holo, const SymOpList *mero) { Reflection *refl; RefListIterator *iter; RefList *out; SymOpMask *m; /* FIXME: Check properly by coset decomposition */ if ( num_equivs(holo, NULL) < num_equivs(mero, NULL) ) { ERROR("%s is not a subgroup of %s!\n", symmetry_name(mero), symmetry_name(holo)); return NULL; } out = reflist_new(); m = new_symopmask(holo); for ( refl = first_refl(in, &iter); refl != NULL; refl = next_refl(refl, iter) ) { double total, sigma; signed int h, k, l; int n, j; int skip; get_indices(refl, &h, &k, &l); /* There is a many-to-one correspondence between reflections * in the merohedral and holohedral groups. Do the calculation * only once for each reflection in the holohedral group, which * contains fewer reflections. */ get_asymm(holo, h, k, l, &h, &k, &l); if ( find_refl(out, h, k, l) != NULL ) continue; total = 0.0; sigma = 0.0; skip = 0; special_position(holo, m, h, k, l); n = num_equivs(holo, m); for ( j=0; j num_equivs(initial, NULL) ) { ERROR("%s is not a subgroup of %s!\n", symmetry_name(initial), symmetry_name(target)); return NULL; } out = reflist_new(); m = new_symopmask(initial); for ( refl = first_refl(in, &iter); refl != NULL; refl = next_refl(refl, iter) ) { signed int h, k, l; int n, j; double intensity; get_indices(refl, &h, &k, &l); intensity = get_intensity(refl); special_position(initial, m, h, k, l); n = num_equivs(initial, m); /* For each equivalent in the higher symmetry group */ for ( j=0; j