/* * ambigator.c * * Resolve indexing ambiguities * * Copyright © 2014 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * Copyright © 2014 Wolfgang Brehm * * Authors: * 2014 Thomas White * 2014 Wolfgang Brehm * * 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 #include #include #include #include #include #include #include #include static void show_help(const char *s) { printf("Syntax: %s [options] input.stream\n\n", s); printf( "Resolve indexing ambiguities.\n" "\n" " -h, --help Display this help message.\n" "\n" " -o, --output= Output stream.\n" " -y, --symmetry= Actual (\"target\") symmetry.\n" " -w Apparent (\"source\" or \"twinned\") symmetry.\n" " -n, --iterations= Iterate times.\n" " --highres= High resolution cutoff in A.\n" " --lowres= Low resolution cutoff in A.\n" ); } #define SERIAL(h, k, l) ((((h)+512)<<20) + (((k)+512)<<10) + ((l)+512)) #define GET_H(serial) ((((serial) & 0x3ff00000)>>20)-512) #define GET_K(serial) ((((serial) & 0x000ffc00)>>10)-512) #define GET_L(serial) (((serial) & 0x000003ff)-512) struct flist { int n; unsigned int *s; unsigned int *s_reidx; float *i; }; static struct flist *asymm_and_merge(RefList *in, const SymOpList *sym, UnitCell *cell, double rmin, double rmax, SymOpList *amb) { Reflection *refl; RefListIterator *iter; RefList *asym; struct flist *f; int n; asym = reflist_new(); if ( asym == NULL ) return NULL; for ( refl = first_refl(in, &iter); refl != NULL; refl = next_refl(refl, iter) ) { signed int h, k, l; signed int ha, ka, la; Reflection *cr; double res; get_indices(refl, &h, &k, &l); res = 2.0*resolution(cell, h, k, l); if ( res < rmin ) continue; if ( res > rmax ) continue; get_asymm(sym, h, k, l, &ha, &ka, &la); cr = find_refl(asym, ha, ka, la); if ( cr == NULL ) { cr = add_refl(asym, ha, ka, la); assert(cr != NULL); copy_data(cr, refl); } else { const double i = get_intensity(cr); const int r = get_redundancy(cr); set_intensity(cr, (r*i + get_intensity(refl))/(r+1)); set_redundancy(cr, r+1); } } f = malloc(sizeof(struct flist)); if ( f == NULL ) { ERROR("Failed to allocate flist\n"); return NULL; } n = num_reflections(asym); f->s = malloc(n*sizeof(unsigned int)); f->s_reidx = malloc(n*sizeof(unsigned int)); f->i = malloc(n*sizeof(float)); if ( (f->s == NULL) || (f->i == NULL) || (f->s_reidx == NULL) ) { ERROR("Failed to allocate flist\n"); return NULL; } f->n = 0; for ( refl = first_refl(asym, &iter); refl != NULL; refl = next_refl(refl, iter) ) { signed int h, k, l; signed int hr, kr, lr; signed int hra, kra, lra; get_indices(refl, &h, &k, &l); f->s[f->n] = SERIAL(h, k, l); if ( amb != NULL ) { get_equiv(amb, NULL, 1, h, k, l, &hr, &kr, &lr); get_asymm(sym, hr, kr, lr, &hra, &kra, &lra); f->s_reidx[f->n] = SERIAL(hra, kra, lra); } f->i[f->n] = get_intensity(refl); f->n++; } reflist_free(asym); assert(f->n == n); return f; } static float corr(struct flist *a, struct flist *b, int *pn, int a_reidx) { float s_xy = 0.0; float s_x = 0.0; float s_y = 0.0; float s_x2 = 0.0; float s_y2 = 0.0; int n = 0; float t1, t2; int ap = 0; int bp = 0; int done = 0; unsigned int *sa; unsigned int *sb; if ( a_reidx ) { sa = a->s_reidx; } else { sa = a->s; } sb = b->s; while ( 1 ) { while ( sa[ap] > sb[bp] ) { if ( ++bp == b->n ) { done = 1; break; } } if ( done ) break; while ( sa[ap] < sb[bp] ) { if ( ++ap == a->n ) { done = 1; break; } } if ( done ) break; if ( sa[ap] == sb[bp] ) { float aint, bint; aint = a->i[ap]; bint = b->i[bp]; s_xy += aint*bint; s_x += aint; s_y += bint; s_x2 += aint*aint; s_y2 += bint*bint; n++; if ( ++ap == a->n ) break; if ( ++bp == b->n ) break; } } *pn = n; t1 = s_x2 - s_x*s_x / n; t2 = s_y2 - s_y*s_y / n; if ( (t1 <= 0.0) || (t2 <= 0.0) ) return 0.0; return (s_xy - s_x*s_y/n) / sqrt(t1*t2); } static void detwin(struct flist **crystals, int n_crystals, int *assignments, SymOpList *amb) { int i; int nch = 0; float mf = 0.0; int nmf = 0; int ndud = 0; for ( i=0; i 2 ) { if ( assignments[i] == assignments[j] ) { f += cc; p++; } else { g += cc; q++; } } if ( (amb != NULL) && (n_reidx > 2) ) { if ( assignments[i] == assignments[j] ) { g += cc_reidx; q++; } else { f += cc_reidx; p++; } } } if ( (p==0) || (q==0) ) { ndud++; continue; } f /= p; g /= q; mf += f; nmf++; if ( f < g ) { assignments[i] = 1 - assignments[i]; nch++; } } if ( ndud > 0 ) { STATUS("Warning: %i crystals had no correlation\n", ndud); } STATUS("Mean f = %f, changed %i assignments this time.\n", mf/nmf, nch); } int main(int argc, char *argv[]) { int c; const char *infile; char *outfile = NULL; char *s_sym_str = NULL; SymOpList *s_sym; char *w_sym_str = NULL; SymOpList *w_sym; SymOpList *amb; int n_iter = 1; int n_crystals, n_chunks, max_crystals; int n_dif; struct flist **crystals; Stream *st; int i; int *assignments; int *orig_assignments; gsl_rng *rng; float highres, lowres; double rmin = 0.0; /* m^-1 */ double rmax = INFINITY; /* m^-1 */ /* Long options */ const struct option longopts[] = { {"help", 0, NULL, 'h'}, {"output", 1, NULL, 'o'}, {"symmetry", 1, NULL, 'y'}, {"iterations", 1, NULL, 'n'}, {"highres", 1, NULL, 2}, {"lowres", 1, NULL, 3}, {0, 0, NULL, 0} }; /* Short options */ while ((c = getopt_long(argc, argv, "ho:y:n:w:", longopts, NULL)) != -1) { switch (c) { case 'h' : show_help(argv[0]); return 0; case 'o' : outfile = strdup(optarg); break; case 'y' : s_sym_str = strdup(optarg); break; case 'w' : w_sym_str = strdup(optarg); break; case 'n' : n_iter = atoi(optarg); break; case 2 : if ( sscanf(optarg, "%e", &highres) != 1 ) { ERROR("Invalid value for --highres\n"); return 1; } rmax = 1.0 / (highres/1e10); break; case 3 : if ( sscanf(optarg, "%e", &lowres) != 1 ) { ERROR("Invalid value for --lowres\n"); return 1; } rmin = 1.0 / (lowres/1e10); break; case 0 : break; case '?' : break; default : ERROR("Unhandled option '%c'\n", c); break; } } if ( argc != (optind+1) ) { ERROR("Please provide exactly one stream filename.\n"); return 1; } infile = argv[optind++]; st = open_stream_for_read(infile); if ( st == NULL ) { ERROR("Failed to open input stream '%s'\n", infile); return 1; } /* Sanitise output filename */ if ( outfile == NULL ) { outfile = strdup("partialator.hkl"); } if ( s_sym_str == NULL ) { ERROR("You must specify the input symmetry (with -y)\n"); return 1; } s_sym = get_pointgroup(s_sym_str); free(s_sym_str); if ( w_sym_str == NULL ) { w_sym = NULL; amb = NULL; } else { w_sym = get_pointgroup(w_sym_str); free(w_sym_str); if ( w_sym == NULL ) return 1; amb = get_ambiguities(w_sym, s_sym); if ( amb == NULL ) return 1; STATUS("Ambiguity operations:\n"); describe_symmetry(amb); } crystals = NULL; n_crystals = 0; max_crystals = 0; n_chunks = 0; do { struct image cur; int i; cur.det = NULL; if ( read_chunk(st, &cur) != 0 ) { break; } image_feature_list_free(cur.features); for ( i=0; i 0.5); orig_assignments[i] = assignments[i]; } for ( i=0; i