From 22951c51e383e8a2f1a01d8bca60e4da9732633c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 17 Oct 2016 17:29:16 +0200 Subject: Initial TakeTwo import Only changes from Helen's code so far: 1. Stripping trailing spaces 2. Tweaking includes (<> -> "") 3. Adding initial CrystFEL hooks at the bottom of taketwo.c 4. Moving definition of struct SpotVec to taketwo.c 5. Removing prototype for run_taketwo from taketwo.h (comment moved to .c) 6. Authorship/copyright boilerplate --- libcrystfel/Makefile.am | 6 +- libcrystfel/src/index.c | 24 +- libcrystfel/src/index.h | 6 + libcrystfel/src/taketwo.c | 819 ++++++++++++++++++++++++++++++++++++++++++++++ libcrystfel/src/taketwo.h | 41 +++ 5 files changed, 892 insertions(+), 4 deletions(-) create mode 100644 libcrystfel/src/taketwo.c create mode 100644 libcrystfel/src/taketwo.h diff --git a/libcrystfel/Makefile.am b/libcrystfel/Makefile.am index d7142f6a..7bb08685 100644 --- a/libcrystfel/Makefile.am +++ b/libcrystfel/Makefile.am @@ -10,7 +10,8 @@ libcrystfel_la_SOURCES = src/reflist.c src/utils.c src/cell.c src/detector.c \ src/render.c src/index.c src/dirax.c src/mosflm.c \ src/cell-utils.c src/integer_matrix.c src/crystal.c \ src/xds.c src/integration.c src/predict-refine.c \ - src/histogram.c src/events.c src/felix.c + src/histogram.c src/events.c src/felix.c \ + src/taketwo.c if HAVE_FFTW libcrystfel_la_SOURCES += src/asdf.c @@ -30,7 +31,8 @@ libcrystfel_la_include_HEADERS = ${top_srcdir}/version.h \ src/integer_matrix.h src/crystal.h \ src/xds.h src/predict-refine.h \ src/integration.h src/histogram.h \ - src/events.h src/asdf.h src/felix.h + src/events.h src/asdf.h src/felix.h \ + src/taketwo.h AM_CPPFLAGS = -DDATADIR=\""$(datadir)"\" -I$(top_builddir)/lib -Wall AM_CPPFLAGS += -I$(top_srcdir)/lib @LIBCRYSTFEL_CFLAGS@ diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index c8c86414..e0bebfa4 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -3,12 +3,12 @@ * * Perform indexing (somehow) * - * Copyright © 2012-2015 Deutsches Elektronen-Synchrotron DESY, + * Copyright © 2012-2016 Deutsches Elektronen-Synchrotron DESY, * a research centre of the Helmholtz Association. * Copyright © 2012 Lorenzo Galli * * Authors: - * 2010-2014 Thomas White + * 2010-2016 Thomas White * 2010-2011 Richard Kirian * 2012 Lorenzo Galli * 2013 Cornelius Gati @@ -56,6 +56,7 @@ #include "cell-utils.h" #include "felix.h" #include "predict-refine.h" +#include "taketwo.h" static int debug_index(struct image *image) @@ -117,6 +118,10 @@ IndexingPrivate **prepare_indexing(IndexingMethod *indm, UnitCell *cell, options); break; + case INDEXING_TAKETWO : + iprivs[n] = taketwo_prepare(&indm[n], cell, det, ltl); + break; + default : ERROR("Don't know how to prepare indexing method %i\n", indm[n]); @@ -193,6 +198,10 @@ void cleanup_indexing(IndexingMethod *indms, IndexingPrivate **privs) free(privs[n]); break; + case INDEXING_TAKETWO : + taketwo_cleanup(privs[n]); + break; + default : ERROR("Don't know how to clean up indexing method %i\n", indms[n]); @@ -268,6 +277,10 @@ static int try_indexer(struct image *image, IndexingMethod indm, r = felix_index(image, ipriv); break; + case INDEXING_TAKETWO : + r = taketwo_index(image, ipriv); + break; + default : ERROR("Unrecognised indexing method: %i\n", indm); return 0; @@ -568,6 +581,10 @@ char *indexer_str(IndexingMethod indm) strcpy(str, "xds"); break; + case INDEXING_TAKETWO : + strcpy(str, "taketwo"); + break; + case INDEXING_SIMULATION : strcpy(str, "simulation"); break; @@ -660,6 +677,9 @@ IndexingMethod *build_indexer_list(const char *str) } else if ( strcmp(methods[i], "felix") == 0) { list[++nmeth] = INDEXING_DEFAULTS_FELIX; + } else if ( strcmp(methods[i], "taketwo") == 0) { + list[++nmeth] = INDEXING_DEFAULTS_TAKETWO; + } else if ( strcmp(methods[i], "none") == 0) { list[++nmeth] = INDEXING_NONE; diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h index 2fb5a13d..6ac9792a 100644 --- a/libcrystfel/src/index.h +++ b/libcrystfel/src/index.h @@ -58,6 +58,10 @@ | INDEXING_USE_CELL_PARAMETERS \ | INDEXING_RETRY | INDEXING_REFINE) +#define INDEXING_DEFAULTS_TAKETWO (INDEXING_TAKETWO \ + | INDEXING_USE_CELL_PARAMETERS \ + | INDEXING_RETRY | INDEXING_REFINE) + /* Axis check is needed for XDS, because it likes to permute the axes */ #define INDEXING_DEFAULTS_XDS (INDEXING_XDS | INDEXING_USE_LATTICE_TYPE \ | INDEXING_USE_CELL_PARAMETERS \ @@ -75,6 +79,7 @@ * @INDEXING_SIMULATION: Dummy value * @INDEXING_DEBUG: Results injector for debugging * @INDEXING_ASDF: Use in-built "asdf" indexer + * @INDEXING_TAKETWO: Use in-built "taketwo" indexer * @INDEXING_CHECK_CELL_COMBINATIONS: Check linear combinations of unit cell * axes for agreement with given cell. * @INDEXING_CHECK_CELL_AXES: Check unit cell axes for agreement with given @@ -107,6 +112,7 @@ typedef enum { INDEXING_SIMULATION = 6, INDEXING_DEBUG = 7, INDEXING_ASDF = 8, + INDEXING_TAKETWO = 9, /* Bits at the top of the IndexingMethod are flags which modify the * behaviour of the indexer. */ diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c new file mode 100644 index 00000000..32300113 --- /dev/null +++ b/libcrystfel/src/taketwo.c @@ -0,0 +1,819 @@ +/* + * taketwo.c + * + * Rewrite of TakeTwo algorithm (Acta D72 (8) 956-965) for CrystFEL + * + * Copyright © 2016 Helen Ginn + * Copyright © 2016 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2016 Helen Ginn + * 2016 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 . + * + */ + +#include +#include + +#include "cell-utils.h" +#include "index.h" +#include "taketwo.h" + +/** + * spotvec + * @obsvec: an observed vector between two spots + * @matches: array of matching theoretical vectors from unit cell + * @match_num: number of matches + * @distance: length of obsvec (do I need this?) + * @her_rlp: pointer to first rlp position for difference vec + * @his_rlp: pointer to second rlp position for difference vec + * + * Structure representing 3D vector between two potential Bragg peaks + * in reciprocal space, and an array of potential matching theoretical + * vectors from unit cell/centering considerations. + **/ +struct SpotVec +{ + struct rvec obsvec; + struct rvec *matches; + int match_num; + double distance; + struct rvec *her_rlp; + struct rvec *his_rlp; +}; + +/* Maximum distance between two rlp sizes to consider info for indexing */ +#define MAX_RECIP_DISTANCE 0.15 + +/* Tolerance for two lengths in reciprocal space to be considered the same */ +#define RECIP_TOLERANCE 0.001 + +/* Threshold for network members to consider a potential solution */ +#define NETWORK_MEMBER_THRESHOLD 20 + +/* Maximum network members (obviously a solution so should stop) */ +#define MAX_NETWORK_MEMBERS 100 + +/* Maximum dead ends for a single branch extension during indexing */ +#define MAX_DEAD_ENDS 5 + +/* FIXME: Tolerance for two angles to be considered the same - is there some + * pre-existing degrees-to-radians in CrystFEL to use here or not? + */ +#define ANGLE_TOLERANCE 1.0 * M_PI / 180 + +/** TODO: + * + * - May need to be capable of playing with the tolerances/#defined stuff. + */ + + +/* ------------------------------------------------------------------------ + * apologetic function + * ------------------------------------------------------------------------*/ + +void apologise() +{ + printf("Error - could not allocate memory for indexing.\n"); +} + +/* ------------------------------------------------------------------------ + * functions concerning aspects of rvec which are very likely to be + * incorporated somewhere else in CrystFEL and therefore may need to be + * deleted and references connected to a pre-existing function. (Lowest level) + * ------------------------------------------------------------------------*/ + +static struct rvec new_rvec(double new_u, double new_v, double new_w) +{ + struct rvec new_rvector; + new_rvector.u = new_u; + new_rvector.v = new_v; + new_rvector.w = new_w; + + return new_rvector; +} + +static struct rvec diff_vec(struct rvec from, struct rvec to) +{ + struct rvec diff = new_rvec(to.u - from.u, + to.v - from.v, + to.w - from.w); + + return diff; +} + +static double sq_length(struct rvec vec) +{ + double sqlength = (vec.u * vec.u + vec.v * vec.v + vec.w * vec.w); + + return sqlength; +} + +static double rvec_length(struct rvec vec) +{ + return sqrt(sq_length(vec)); +} + +static void normalise_rvec(struct rvec *vec) +{ + double length = rvec_length(*vec); + vec->u /= length; + vec->v /= length; + vec->w /= length; +} + +static double rvec_cosine(struct rvec v1, struct rvec v2) +{ + double dot_prod = v1.u * v2.u + v1.v * v2.v + v1.w * v2.w; + double v1_length = rvec_length(v1); + double v2_length = rvec_length(v2); + + double cos_theta = dot_prod / (v1_length * v2_length); + + return cos_theta; +} + +static double rvec_angle(struct rvec v1, struct rvec v2) +{ + double cos_theta = rvec_cosine(v1, v2); + double angle = acos(cos_theta); + + return angle; +} + +/* ------------------------------------------------------------------------ + * functions called under the core functions, still specialised (Level 3) + * ------------------------------------------------------------------------*/ + +/* Rotate vector (vec1) around axis (axis) by angle theta. Find value of + * theta for which the angle between (vec1) and (vec2) is minimised. + * Behold! Finally an analytical solution for this one. Assuming + * that @result has already been allocated. Will upload the maths to the + * shared Google drive. */ +static int closest_rot_mat(struct rvec vec1, struct rvec vec2, + struct rvec axis, gsl_matrix *result) +{ + /* Let's have unit vectors */ + normalise_rvec(&vec1); + normalise_rvec(&vec2); + normalise_rvec(&axis); + + /* Redeclaring these to try and maintain readability and + * check-ability against the maths I wrote down */ + double a = vec2.u; double b = vec2.w; double c = vec2.v; + double p = vec1.u; double q = vec1.w; double r = vec1.v; + double x = axis.u; double y = axis.w; double z = axis.v; + + /* Components in handwritten maths online when I upload it */ + double A = a*(p*x*x - p + x*y*q + x*z*r) + + b*(p*x*y + q*y*y - q + r*y*z) + + c*(p*x*z + q*y*z + r*z*z - r); + + double B = a*(y*r - z*q) + b*(p*z - r*x) + c*(q*x - p*y); + + double tan_theta = - B / A; + + /* Not sure why I always have to take the + M_PI solution. Work + * this one out. But it always works!? */ + double theta = atan(tan_theta) + M_PI; + + /* FIXME: fill in the gsl_matrix *result with an identity matrix + * which has subsequently been rotated by theta around the axis. + * Help from Tom, probably. */ + + result = result; + + return 1; +} + +static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) +{ + /* FIXME: write me! + * Write code for that fancy algorithm here from XPLOR */ + + return 0; +} + +/* Code me in gsl_matrix language to copy the contents of the function + * in cppxfel (IndexingSolution::createSolution). This function is quite + * intensive on the number crunching side so simple angle checks are used + * to 'pre-scan' vectors beforehand. */ +static int generate_rot_mat(struct rvec obs1, struct rvec obs2, + struct rvec cell1, struct rvec cell2, + gsl_matrix *mat) +{ + /* FIXME: Write this code - assume *mat has already been allocated + * and insert a CrystFEL-friendly rotation matrix. Help from Tom. */ + return 1; +} + +static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) +{ + /* FIXME: Disgusting... can I tone this down a bit? */ + if ( (her_obs->her_rlp == his_obs->her_rlp) || + (her_obs->her_rlp == his_obs->his_rlp) || + (her_obs->his_rlp == his_obs->her_rlp) || + (her_obs->his_rlp == his_obs->his_rlp) ) { + return 1; + } + + return 0; +} + +static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, + int *members[MAX_NETWORK_MEMBERS], int num) +{ + int i; + struct SpotVec *her_obs = &obs_vecs[test_idx]; + + for ( i=0; iobsvec, his_obs->obsvec); + + /* calculate angle between all potential theoretical vectors */ + + for ( i=0; imatch_num; i++ ) { + for ( j=0; jmatch_num; j++ ) { + + struct rvec *her_match = &her_obs->matches[i]; + struct rvec *his_match = &his_obs->matches[j]; + + double theory_angle = rvec_angle(*her_match, *his_match); + + /* is this angle a match? */ + + double angle_diff = fabs(theory_angle - obs_angle); + + if ( angle_diff < ANGLE_TOLERANCE ) { + *her_match_idx = i; + *his_match_idx = j; + + return 1; + } + } + } + + return 0; +} + +static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, + int *members[MAX_NETWORK_MEMBERS], int num) +{ + /* note: this is just a preliminary check to reduce unnecessary + * computation later down the line, but is not entirely accurate. + * For example, I have not checked that the 'matching cell vector' + * is identical - too much faff. + **/ + + int i; + struct SpotVec *her_obs = &obs_vecs[test_idx]; + + for ( i=0; i MAX_DEAD_ENDS ) { + break; + } + + /* We have not had too many dead ends. Try removing + the last member and continue. */ + int failed = members[member_num - 1]; + start = failed + 1; + member_num--; + dead_ends++; + + continue; + } + + /* we have elongated membership - so reset dead_ends counter */ + dead_ends = 0; + + members[member_num] = next_index; + start = next_index + 1; + member_num++; + + /* If member_num is high enough, we want to return a yes */ + + if ( member_num > NETWORK_MEMBER_THRESHOLD ) { + break; + } + } + + /* Deal with this shit after coffee */ + + return ( member_num > NETWORK_MEMBER_THRESHOLD ); +} + +static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, + gsl_matrix **rotation) +{ + /* loop round pairs of vectors to try and find a suitable + * seed to start building a self-consistent network of vectors + */ + int i, j; + + for ( i=0; i RECIP_TOLERANCE ) { + continue; + } + + /* we have a match, add to array! */ + + count++; + int new_size = count*sizeof(struct rvec); + struct rvec *temp_matches; + temp_matches = realloc(obs_vecs[i].matches, new_size); + + if ( temp_matches == NULL ) { + return 0; + } else { + obs_vecs[i].matches = temp_matches; + temp_matches[count - 1] = cell_vecs[j]; + obs_vecs[i].match_num = count; + } + } + } + + return 1; +} + +static int gen_observed_vecs(struct rvec *rlps, int rlp_count, + struct SpotVec **obs_vecs, int *obs_vec_count) +{ + int i, j; + int count = 0; + + /* maximum distance squared for comparisons */ + double max_sq_length = pow(MAX_RECIP_DISTANCE, 2); + + /* Indentation... bending the rules a bit? */ + for ( i=0; i max_sq_length ) { + continue; + } + + count++; + + struct SpotVec *temp_obs_vecs; + temp_obs_vecs = realloc(*obs_vecs, + count*sizeof(struct SpotVec)); + + if ( temp_obs_vecs == NULL ) { + return 0; + } else { + *obs_vecs = temp_obs_vecs; + + /* initialise all SpotVec struct members */ + + struct SpotVec spot_vec; + spot_vec.obsvec = diff; + spot_vec.distance = sqrt(sqlength); + spot_vec.matches = NULL; + spot_vec.match_num = 0; + spot_vec.her_rlp = &rlps[i]; + spot_vec.his_rlp = &rlps[j]; + + (*obs_vecs)[count - 1] = spot_vec; + } + } + } + + *obs_vec_count = count; + + return 1; +} + +static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, + int *vec_count) +{ + double a, b, c, alpha, beta, gamma; + int h_max, k_max, l_max; + + cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma); + + /* find maximum Miller (h, k, l) indices for a given resolution */ + h_max = MAX_RECIP_DISTANCE / a + 1; + k_max = MAX_RECIP_DISTANCE / b + 1; + l_max = MAX_RECIP_DISTANCE / c + 1; + + int h, k, l; + int count = 0; + + for ( h=-h_max; h<=+h_max; h++ ) { + for ( k=-k_max; k<=+k_max; k++ ) { + for ( l=-l_max; l<=+l_max; l++ ) { + + /* Exclude systematic absences from centering concerns */ + if ( forbidden_reflection(cell, h, k, l) ) { + continue; + } + + struct rvec cell_vec = new_rvec(h, k, l); + + /* FIXME: transform int (h, k, l) to reciprocal coordinates. + * Don't want to do this manually if there is already a + * function in libcrystfel to do this. Would like to map + * Miller index (5, 13, 2) onto (0.05, 0.13, 0.02) for example, + * if I had a 100 x 100 x 100 Å cubic cell. */ + + cell_vec = cell_vec; + + /* Assumption that "cell_vec" now has transformed coords */ + + /* add this to our array - which may require expanding */ + count++; + + struct rvec *temp_cell_vecs; + temp_cell_vecs = realloc(*cell_vecs, count*sizeof(struct rvec)); + + if ( temp_cell_vecs == NULL ) { + return 0; + } else { + *cell_vecs = temp_cell_vecs; + (*cell_vecs)[count - 1] = cell_vec; + } + } + } + } + + *vec_count = count; + + return 1; +} + +static void generate_basis_vectors(UnitCell *cell, gsl_matrix *rot, + struct rvec *a_star, struct rvec *b_star, + struct rvec *c_star) +{ + /* FIXME: more matrix stuff - multiply cell matrix by rotation matrix + * and extract the reciprocal axes from the definition of the matrix. + */ +} + +/* ------------------------------------------------------------------------ + * cleanup functions - called from run_taketwo(). + * ------------------------------------------------------------------------*/ + +static int cleanup_taketwo_cell_vecs(struct rvec *cell_vecs) +{ + free(cell_vecs); +} + +static int cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, + int obs_vec_count) +{ + for ( int i=0; iltl = ltl; + tp->template = cell; + tp->indm = *indm; + + return (IndexingPrivate *)tp; +} + + +void taketwo_cleanup(IndexingPrivate *pp) +{ + struct taketwo_private *tp = (struct taketwo_private *)pp; + free(tp); +} diff --git a/libcrystfel/src/taketwo.h b/libcrystfel/src/taketwo.h new file mode 100644 index 00000000..35f7cbe3 --- /dev/null +++ b/libcrystfel/src/taketwo.h @@ -0,0 +1,41 @@ +/* + * taketwo.h + * + * Rewrite of TakeTwo algorithm (Acta D72 (8) 956-965) for CrystFEL + * + * Copyright © 2016 Helen Ginn + * Copyright © 2016 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2016 Helen Ginn + * 2016 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 . + * + */ + +#ifndef TAKETWO_H +#define TAKETWO_H + +#include "cell.h" + +extern IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, + struct detector *det, float *ltl); +extern int taketwo_index(struct image *image, IndexingPrivate *ipriv); +extern void taketwo_cleanup(IndexingPrivate *pp); + +#endif /* TAKETWO_H */ -- cgit v1.2.3 From c6d507e2e4fd9732bbfeee3295187e95df100271 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 14:54:22 +0200 Subject: Stuff to make it compile --- libcrystfel/src/taketwo.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 32300113..e1709b2b 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -58,6 +58,15 @@ struct SpotVec struct rvec *his_rlp; }; + +struct taketwo_private +{ + IndexingMethod indm; + float *ltl; + UnitCell *cell; +}; + + /* Maximum distance between two rlp sizes to consider info for indexing */ #define MAX_RECIP_DISTANCE 0.15 @@ -432,18 +441,17 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, (int **)&members, start, member_num); + if ( member_num < 2 ) return 0; + if ( next_index < 0 ) { /* If there have been too many dead ends, give up * on indexing altogether. **/ - if ( dead_ends > MAX_DEAD_ENDS ) { - break; - } + if ( dead_ends > MAX_DEAD_ENDS ) break; /* We have not had too many dead ends. Try removing the last member and continue. */ - int failed = members[member_num - 1]; - start = failed + 1; + start = members[member_num - 1] + 1; member_num--; dead_ends++; @@ -698,15 +706,16 @@ static void generate_basis_vectors(UnitCell *cell, gsl_matrix *rot, * cleanup functions - called from run_taketwo(). * ------------------------------------------------------------------------*/ -static int cleanup_taketwo_cell_vecs(struct rvec *cell_vecs) +static void cleanup_taketwo_cell_vecs(struct rvec *cell_vecs) { free(cell_vecs); } -static int cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, +static void cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, int obs_vec_count) { - for ( int i=0; iltl = ltl; - tp->template = cell; + tp->cell = cell; tp->indm = *indm; return (IndexingPrivate *)tp; -- cgit v1.2.3 From ca9cd76c5eb380b947231456cf7bd5cd7139a7c1 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 16:56:18 +0200 Subject: ANGLE_TOLERANCE --- libcrystfel/src/taketwo.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index e1709b2b..9c4dd9e2 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -82,10 +82,8 @@ struct taketwo_private /* Maximum dead ends for a single branch extension during indexing */ #define MAX_DEAD_ENDS 5 -/* FIXME: Tolerance for two angles to be considered the same - is there some - * pre-existing degrees-to-radians in CrystFEL to use here or not? - */ -#define ANGLE_TOLERANCE 1.0 * M_PI / 180 +/* Tolerance for two angles to be considered the same */ +#define ANGLE_TOLERANCE (deg2rad(1.0)) /** TODO: * -- cgit v1.2.3 From 28d979a473da34d5da562d988aa04ed370b09080 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 16:57:03 +0200 Subject: rotation_between_vectors --- libcrystfel/src/taketwo.c | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 9c4dd9e2..72ca414e 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -164,6 +164,18 @@ static double rvec_angle(struct rvec v1, struct rvec v2) return angle; } +static struct rvec rvec_cross(struct rvec a, struct rvec b) +{ + struct rvec c; + + c.u = a.v*b.w - a.w*b.v; + c.v = -(a.u*b.w - a.w*b.u); + c.w = a.u*b.v - a.v-b.u; + + return c; +} + + /* ------------------------------------------------------------------------ * functions called under the core functions, still specialised (Level 3) * ------------------------------------------------------------------------*/ @@ -217,6 +229,29 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) return 0; } + +static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) +{ + double th = rvec_angle(a, b); + struct rvec c = rvec_cross(a, b); + gsl_matrix *res = gsl_matrix_alloc(3, 3); + double omc = 1.0 - cos(th); + double s = sin(th); + + gsl_matrix_set(res, 0, 0, cos(th) + c.u*c.u*omc); + gsl_matrix_set(res, 0, 1, c.u*c.v*omc - c.w*s); + gsl_matrix_set(res, 0, 2, c.u*c.w*omc + c.v*s); + gsl_matrix_set(res, 1, 0, c.u*c.v*omc + c.w*s); + gsl_matrix_set(res, 1, 1, cos(th) + c.v*c.v*omc); + gsl_matrix_set(res, 1, 2, c.v*c.w*omc - c.u*s); + gsl_matrix_set(res, 2, 0, c.w*c.u*omc - c.v*s); + gsl_matrix_set(res, 2, 1, c.w*c.v*omc + c.u*s); + gsl_matrix_set(res, 2, 2, cos(th) + c.w*c.w*omc); + + return res; +} + + /* Code me in gsl_matrix language to copy the contents of the function * in cppxfel (IndexingSolution::createSolution). This function is quite * intensive on the number crunching side so simple angle checks are used @@ -225,8 +260,13 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, struct rvec cell1, struct rvec cell2, gsl_matrix *mat) { - /* FIXME: Write this code - assume *mat has already been allocated - * and insert a CrystFEL-friendly rotation matrix. Help from Tom. */ + gsl_matrix *rotateSpotDiffMatrix; + gsl_matrix *secondTwizzleMatrix; + gsl_matrix *fullMat; + + /* Rotate reciprocal space so that the first observed vector lines up + * with the simulated vector. */ + rotateSpotDiffMatrix = rotation_between_vectors(obs1, cell1); return 1; } -- cgit v1.2.3 From dd1d51b027b04ce4112487b78fd336417b511806 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 17:23:47 +0200 Subject: Rotate obs2 --- libcrystfel/src/taketwo.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 72ca414e..bb5fb975 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -29,6 +29,7 @@ */ #include +#include #include #include "cell-utils.h" @@ -252,6 +253,16 @@ static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) } +static gsl_vector *rvec_to_gsl(struct rvec v) +{ + gsl_vector *a = gsl_vector_alloc(3); + gsl_vector_set(a, 0, v.u); + gsl_vector_set(a, 1, v.v); + gsl_vector_set(a, 2, v.w); + return a; +} + + /* Code me in gsl_matrix language to copy the contents of the function * in cppxfel (IndexingSolution::createSolution). This function is quite * intensive on the number crunching side so simple angle checks are used @@ -263,10 +274,18 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; gsl_matrix *fullMat; + gsl_vector *zero = gsl_vector_calloc(3); + gsl_vector *obs2v = rvec_to_gsl(obs2); /* Rotate reciprocal space so that the first observed vector lines up * with the simulated vector. */ rotateSpotDiffMatrix = rotation_between_vectors(obs1, cell1); + + normalise_rvec(&cell1); + + /* Multiply obs2 by rotateSpotDiffMatrix */ + gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, obs2v, + 0.0, zero); return 1; } -- cgit v1.2.3 From 6b9d9cdc1756d152281cf864058c800719b5e895 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 17:43:52 +0200 Subject: Fixup last commit --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index bb5fb975..f8194421 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -274,8 +274,8 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; gsl_matrix *fullMat; - gsl_vector *zero = gsl_vector_calloc(3); gsl_vector *obs2v = rvec_to_gsl(obs2); + gsl_vector *obs2vr = gsl_vector_calloc(3); /* Rotate reciprocal space so that the first observed vector lines up * with the simulated vector. */ @@ -283,9 +283,9 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, normalise_rvec(&cell1); - /* Multiply obs2 by rotateSpotDiffMatrix */ + /* Multiply obs2 by rotateSpotDiffMatrix --> obs2vr */ gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, obs2v, - 0.0, zero); + 0.0, obs2vr); return 1; } -- cgit v1.2.3 From caa6bf476a07a08fd7a58aec4cba9d59f57364ba Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 17:44:20 +0200 Subject: Implmement closest_rot_mat --- libcrystfel/src/taketwo.c | 87 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index f8194421..3024a9d8 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -181,47 +181,64 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) * functions called under the core functions, still specialised (Level 3) * ------------------------------------------------------------------------*/ +static gsl_matrix *rotation_around_axis(struct rvec c, double th) +{ + double omc = 1.0 - cos(th); + double s = sin(th); + gsl_matrix *res = gsl_matrix_alloc(3, 3); + + gsl_matrix_set(res, 0, 0, cos(th) + c.u*c.u*omc); + gsl_matrix_set(res, 0, 1, c.u*c.v*omc - c.w*s); + gsl_matrix_set(res, 0, 2, c.u*c.w*omc + c.v*s); + gsl_matrix_set(res, 1, 0, c.u*c.v*omc + c.w*s); + gsl_matrix_set(res, 1, 1, cos(th) + c.v*c.v*omc); + gsl_matrix_set(res, 1, 2, c.v*c.w*omc - c.u*s); + gsl_matrix_set(res, 2, 0, c.w*c.u*omc - c.v*s); + gsl_matrix_set(res, 2, 1, c.w*c.v*omc + c.u*s); + gsl_matrix_set(res, 2, 2, cos(th) + c.w*c.w*omc); + + return res; +} + + /* Rotate vector (vec1) around axis (axis) by angle theta. Find value of * theta for which the angle between (vec1) and (vec2) is minimised. * Behold! Finally an analytical solution for this one. Assuming * that @result has already been allocated. Will upload the maths to the * shared Google drive. */ -static int closest_rot_mat(struct rvec vec1, struct rvec vec2, - struct rvec axis, gsl_matrix *result) +static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, + struct rvec axis) { - /* Let's have unit vectors */ - normalise_rvec(&vec1); - normalise_rvec(&vec2); - normalise_rvec(&axis); + /* Let's have unit vectors */ + normalise_rvec(&vec1); + normalise_rvec(&vec2); + normalise_rvec(&axis); - /* Redeclaring these to try and maintain readability and - * check-ability against the maths I wrote down */ - double a = vec2.u; double b = vec2.w; double c = vec2.v; - double p = vec1.u; double q = vec1.w; double r = vec1.v; - double x = axis.u; double y = axis.w; double z = axis.v; + /* Redeclaring these to try and maintain readability and + * check-ability against the maths I wrote down */ + double a = vec2.u; double b = vec2.w; double c = vec2.v; + double p = vec1.u; double q = vec1.w; double r = vec1.v; + double x = axis.u; double y = axis.w; double z = axis.v; - /* Components in handwritten maths online when I upload it */ - double A = a*(p*x*x - p + x*y*q + x*z*r) + - b*(p*x*y + q*y*y - q + r*y*z) + - c*(p*x*z + q*y*z + r*z*z - r); + /* Components in handwritten maths online when I upload it */ + double A = a*(p*x*x - p + x*y*q + x*z*r) + + b*(p*x*y + q*y*y - q + r*y*z) + + c*(p*x*z + q*y*z + r*z*z - r); - double B = a*(y*r - z*q) + b*(p*z - r*x) + c*(q*x - p*y); + double B = a*(y*r - z*q) + b*(p*z - r*x) + c*(q*x - p*y); - double tan_theta = - B / A; + double tan_theta = - B / A; - /* Not sure why I always have to take the + M_PI solution. Work - * this one out. But it always works!? */ - double theta = atan(tan_theta) + M_PI; + /* Not sure why I always have to take the + M_PI solution. Work + * this one out. But it always works!? */ + double theta = atan(tan_theta) + M_PI; - /* FIXME: fill in the gsl_matrix *result with an identity matrix - * which has subsequently been rotated by theta around the axis. - * Help from Tom, probably. */ - - result = result; - - return 1; + /* Return an identity matrix which has been rotated by + * theta around "axis" */ + return rotation_around_axis(axis, theta); } + static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) { /* FIXME: write me! @@ -235,21 +252,7 @@ static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) { double th = rvec_angle(a, b); struct rvec c = rvec_cross(a, b); - gsl_matrix *res = gsl_matrix_alloc(3, 3); - double omc = 1.0 - cos(th); - double s = sin(th); - - gsl_matrix_set(res, 0, 0, cos(th) + c.u*c.u*omc); - gsl_matrix_set(res, 0, 1, c.u*c.v*omc - c.w*s); - gsl_matrix_set(res, 0, 2, c.u*c.w*omc + c.v*s); - gsl_matrix_set(res, 1, 0, c.u*c.v*omc + c.w*s); - gsl_matrix_set(res, 1, 1, cos(th) + c.v*c.v*omc); - gsl_matrix_set(res, 1, 2, c.v*c.w*omc - c.u*s); - gsl_matrix_set(res, 2, 0, c.w*c.u*omc - c.v*s); - gsl_matrix_set(res, 2, 1, c.w*c.v*omc + c.u*s); - gsl_matrix_set(res, 2, 2, cos(th) + c.w*c.w*omc); - - return res; + return rotation_around_axis(c, th); } -- cgit v1.2.3 From 92aaa33d870c10fc832247e2aa02de535072f992 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 17:46:23 +0200 Subject: secondTwizzleMatrix --- libcrystfel/src/taketwo.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 3024a9d8..1411b8a7 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -289,6 +289,10 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Multiply obs2 by rotateSpotDiffMatrix --> obs2vr */ gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, obs2v, 0.0, obs2vr); + + /* Now we twirl around the firstAxisUnit until the rotated observed + * vector matches the second simulated vector as closely as possible. */ + secondTwizzleMatrix = closest_rotmat(obs2vr, cell2, cell1); return 1; } -- cgit v1.2.3 From e711b80ba12fd1393628cb15a838281566195b2c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 18 Oct 2016 17:47:28 +0200 Subject: Fix up last commit --- libcrystfel/src/taketwo.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 1411b8a7..21686cd1 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -266,6 +266,16 @@ static gsl_vector *rvec_to_gsl(struct rvec v) } +struct rvec gsl_to_rvec(gsl_vector *a) +{ + struct rvec v; + v.u = gsl_vector_get(a, 0); + v.v = gsl_vector_get(a, 1); + v.w = gsl_vector_get(a, 2); + return v; +} + + /* Code me in gsl_matrix language to copy the contents of the function * in cppxfel (IndexingSolution::createSolution). This function is quite * intensive on the number crunching side so simple angle checks are used @@ -292,7 +302,7 @@ static int generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Now we twirl around the firstAxisUnit until the rotated observed * vector matches the second simulated vector as closely as possible. */ - secondTwizzleMatrix = closest_rotmat(obs2vr, cell2, cell1); + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(obs2vr), cell2, cell1); return 1; } -- cgit v1.2.3 From 59a2678647cd5df865a72c83543a4b1bc5e46be8 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 10:35:35 +0200 Subject: Fussiness (extreme) --- libcrystfel/src/taketwo.c | 72 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 21686cd1..90a32891 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -117,6 +117,7 @@ static struct rvec new_rvec(double new_u, double new_v, double new_w) return new_rvector; } + static struct rvec diff_vec(struct rvec from, struct rvec to) { struct rvec diff = new_rvec(to.u - from.u, @@ -133,11 +134,13 @@ static double sq_length(struct rvec vec) return sqlength; } + static double rvec_length(struct rvec vec) { return sqrt(sq_length(vec)); } + static void normalise_rvec(struct rvec *vec) { double length = rvec_length(*vec); @@ -146,6 +149,7 @@ static void normalise_rvec(struct rvec *vec) vec->w /= length; } + static double rvec_cosine(struct rvec v1, struct rvec v2) { double dot_prod = v1.u * v2.u + v1.v * v2.v + v1.w * v2.w; @@ -157,6 +161,7 @@ static double rvec_cosine(struct rvec v1, struct rvec v2) return cos_theta; } + static double rvec_angle(struct rvec v1, struct rvec v2) { double cos_theta = rvec_cosine(v1, v2); @@ -165,6 +170,7 @@ static double rvec_angle(struct rvec v1, struct rvec v2) return angle; } + static struct rvec rvec_cross(struct rvec a, struct rvec b) { struct rvec c; @@ -280,32 +286,40 @@ struct rvec gsl_to_rvec(gsl_vector *a) * in cppxfel (IndexingSolution::createSolution). This function is quite * intensive on the number crunching side so simple angle checks are used * to 'pre-scan' vectors beforehand. */ -static int generate_rot_mat(struct rvec obs1, struct rvec obs2, - struct rvec cell1, struct rvec cell2, - gsl_matrix *mat) +static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, + struct rvec cell1, struct rvec cell2) { gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; gsl_matrix *fullMat; - gsl_vector *obs2v = rvec_to_gsl(obs2); - gsl_vector *obs2vr = gsl_vector_calloc(3); + gsl_vector *cell2v = rvec_to_gsl(cell2); + gsl_vector *cell2vr = gsl_vector_calloc(3); - /* Rotate reciprocal space so that the first observed vector lines up - * with the simulated vector. */ - rotateSpotDiffMatrix = rotation_between_vectors(obs1, cell1); + /* Rotate reciprocal space so that the first simulated vector lines up + * with the observed vector. */ + rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); - normalise_rvec(&cell1); + normalise_rvec(&obs1); - /* Multiply obs2 by rotateSpotDiffMatrix --> obs2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, obs2v, - 0.0, obs2vr); + /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ + gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, + 0.0, cell2vr); - /* Now we twirl around the firstAxisUnit until the rotated observed - * vector matches the second simulated vector as closely as possible. */ - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(obs2vr), cell2, cell1); - return 1; + /* Now we twirl around the firstAxisUnit until the rotated simulated + * vector matches the second observed vector as closely as possible. */ + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), + obs2, obs1); + + /* We want to apply the first matrix and then the second matrix, + * so we multiply these. */ + fullMat = gsl_matrix_calloc(3, 3); + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, + secondTwizzleMatrix, rotateSpotDiffMatrix, 0.0, fullMat); + + return fullMat; } + static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) { /* FIXME: Disgusting... can I tone this down a bit? */ @@ -319,6 +333,7 @@ static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) return 0; } + static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, int *members[MAX_NETWORK_MEMBERS], int num) { @@ -338,6 +353,7 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, return 0; } + /** Note: this could potentially (and cautiously) converted to comparing * cosines rather than angles, to lose an "acos" but different parts of the * cosine graph are more sensitive than others, so may be a trade off... or not. @@ -377,6 +393,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, return 0; } + static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, int *members[MAX_NETWORK_MEMBERS], int num) { @@ -467,10 +484,10 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, gsl_matrix *test_rot = gsl_matrix_calloc(3, 3); int j_idx = (*members)[j]; - generate_rot_mat(obs_vecs[j_idx].obsvec, - obs_vecs[i].obsvec, - *member_match, - *test_match, test_rot); + test_rot = generate_rot_mat(obs_vecs[j_idx].obsvec, + obs_vecs[i].obsvec, + *member_match, + *test_match); ok = rot_mats_are_similar(rot, test_rot); } @@ -489,6 +506,7 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, return -1; } + static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int obs_vec_count, int obs_idx1, int obs_idx2) { @@ -551,6 +569,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, return ( member_num > NETWORK_MEMBER_THRESHOLD ); } + static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, gsl_matrix **rotation) { @@ -590,9 +609,10 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); - generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, - obs_vecs[i].matches[i_idx], - obs_vecs[j].matches[j_idx], rot_mat); + rot_mat = generate_rot_mat(obs_vecs[i].obsvec, + obs_vecs[j].obsvec, + obs_vecs[i].matches[i_idx], + obs_vecs[j].matches[j_idx]); /* try to expand this rotation matrix to a larger network */ @@ -613,6 +633,7 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, return 0; } + static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, struct SpotVec *obs_vecs, int obs_vec_count) { @@ -655,6 +676,7 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, return 1; } + static int gen_observed_vecs(struct rvec *rlps, int rlp_count, struct SpotVec **obs_vecs, int *obs_vec_count) { @@ -709,6 +731,7 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, return 1; } + static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, int *vec_count) { @@ -767,6 +790,7 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, return 1; } + static void generate_basis_vectors(UnitCell *cell, gsl_matrix *rot, struct rvec *a_star, struct rvec *b_star, struct rvec *c_star) @@ -785,6 +809,7 @@ static void cleanup_taketwo_cell_vecs(struct rvec *cell_vecs) free(cell_vecs); } + static void cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, int obs_vec_count) { @@ -796,6 +821,7 @@ static void cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, free(obs_vecs); } + /* ------------------------------------------------------------------------ * external functions - top level functions (Level 1) * ------------------------------------------------------------------------*/ -- cgit v1.2.3 From f3e5525294b00206ac953f1966eeb0a740829282 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 11:32:04 +0200 Subject: rot_mats_are_similar --- libcrystfel/src/taketwo.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 90a32891..e4b7c8a8 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "cell-utils.h" #include "index.h" @@ -245,12 +246,36 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, } +static double matrix_trace(gsl_matrix *a) +{ + int i; + double tr = 0.0; + + assert(a->size1 == a->size2); + for ( i=0; isize1; a++ ) { + tr += gsl_matrix_get(a, i, i); + } + return tr; +} + + static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) { - /* FIXME: write me! - * Write code for that fancy algorithm here from XPLOR */ + double tr; + gsl_matrix *sub; + gsl_matrix *mul; - return 0; + sub = gsl_matrix_calloc(3, 3); + gsl_matrix_memcpy(sub, rot1); + gsl_matrix_sub(sub, rot2); /* sub = rot1 - rot2 */ + + mul = gsl_matrix_calloc(3, 3); + gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, sub, sub, 0.0, mul); + + tr = matrix_trace(mul); + gsl_matrix_free(mul); + + return tr < sqrt(4.0*(1.0-cos(ANGLE_TOLERANCE)));; } -- cgit v1.2.3 From 508df3a968c08bf262b059a6e0d6e8edefc7401e Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 11:32:20 +0200 Subject: gen_theoretical_vecs --- libcrystfel/src/taketwo.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index e4b7c8a8..55b347d7 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -762,6 +762,9 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, { double a, b, c, alpha, beta, gamma; int h_max, k_max, l_max; + double asx, asy, asz; + double bsx, bsy, bsz; + double csx, csy, csz; cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma); @@ -773,26 +776,22 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, int h, k, l; int count = 0; + cell_get_reciprocal(cell, &asx, &asy, &asz, + &bsx, &bsy, &bsz, + &csx, &csy, &csz); + for ( h=-h_max; h<=+h_max; h++ ) { for ( k=-k_max; k<=+k_max; k++ ) { for ( l=-l_max; l<=+l_max; l++ ) { - /* Exclude systematic absences from centering concerns */ - if ( forbidden_reflection(cell, h, k, l) ) { - continue; - } + struct rvec cell_vec; - struct rvec cell_vec = new_rvec(h, k, l); - - /* FIXME: transform int (h, k, l) to reciprocal coordinates. - * Don't want to do this manually if there is already a - * function in libcrystfel to do this. Would like to map - * Miller index (5, 13, 2) onto (0.05, 0.13, 0.02) for example, - * if I had a 100 x 100 x 100 Å cubic cell. */ - - cell_vec = cell_vec; + /* Exclude systematic absences from centering concerns */ + if ( forbidden_reflection(cell, h, k, l) ) continue; - /* Assumption that "cell_vec" now has transformed coords */ + cell_vec.u = h*asx + k*bsx + l*csx; + cell_vec.v = h*asy + k*bsy + l*csy; + cell_vec.w = h*asz + k*bsz + l*csz; /* add this to our array - which may require expanding */ count++; -- cgit v1.2.3 From 22a20b5b3374a4c776c6efcbed738434cc1c9a6b Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 12:02:45 +0200 Subject: Add transform_cell_gsl() --- libcrystfel/src/cell-utils.c | 44 +++++++++++++++++++++++++++++++++++++++++++- libcrystfel/src/cell-utils.h | 3 +++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c index 69d4174a..74a6b905 100644 --- a/libcrystfel/src/cell-utils.c +++ b/libcrystfel/src/cell-utils.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include "cell.h" @@ -1432,6 +1431,49 @@ void cell_fudge_gslcblas() } +UnitCell *transform_cell_gsl(UnitCell *in, gsl_matrix *m) +{ + gsl_matrix *c; + double asx, asy, asz; + double bsx, bsy, bsz; + double csx, csy, csz; + gsl_matrix *res; + UnitCell *out; + + cell_get_reciprocal(in, &asx, &asy, &asz, &bsx, &bsy, + &bsz, &csx, &csy, &csz); + + c = gsl_matrix_alloc(3, 3); + gsl_matrix_set(c, 0, 0, asx); + gsl_matrix_set(c, 0, 1, asy); + gsl_matrix_set(c, 0, 2, asz); + gsl_matrix_set(c, 1, 0, bsx); + gsl_matrix_set(c, 1, 1, bsy); + gsl_matrix_set(c, 1, 2, bsz); + gsl_matrix_set(c, 2, 0, csx); + gsl_matrix_set(c, 2, 1, csy); + gsl_matrix_set(c, 2, 2, csz); + + res = gsl_matrix_calloc(3, 3); + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, m, c, 0.0, res); + + out = cell_new_from_cell(in); + cell_set_reciprocal(out, gsl_matrix_get(res, 0, 0), + gsl_matrix_get(res, 0, 1), + gsl_matrix_get(res, 0, 2), + gsl_matrix_get(res, 1, 0), + gsl_matrix_get(res, 1, 1), + gsl_matrix_get(res, 1, 2), + gsl_matrix_get(res, 2, 0), + gsl_matrix_get(res, 2, 1), + gsl_matrix_get(res, 2, 2)); + + gsl_matrix_free(res); + gsl_matrix_free(c); + return out; +} + + /** * rotate_cell: * @in: A %UnitCell to rotate diff --git a/libcrystfel/src/cell-utils.h b/libcrystfel/src/cell-utils.h index 000c863a..efb4b25b 100644 --- a/libcrystfel/src/cell-utils.h +++ b/libcrystfel/src/cell-utils.h @@ -35,6 +35,8 @@ #include #endif +#include + #include "cell.h" #ifdef __cplusplus @@ -47,6 +49,7 @@ extern double resolution(UnitCell *cell, extern UnitCell *cell_rotate(UnitCell *in, struct quaternion quat); extern UnitCell *rotate_cell(UnitCell *in, double omega, double phi, double rot); +extern UnitCell *transform_cell_gsl(UnitCell *in, gsl_matrix *m); extern void cell_print(UnitCell *cell); -- cgit v1.2.3 From 5d71f98e2655c6a6738e11040bdb3970cb1406f8 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 12:03:12 +0200 Subject: Generate the resulting cell --- libcrystfel/src/taketwo.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 55b347d7..f3b9da5a 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -90,6 +90,7 @@ struct taketwo_private /** TODO: * * - May need to be capable of playing with the tolerances/#defined stuff. + * - Multiple lattices */ @@ -815,15 +816,6 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, } -static void generate_basis_vectors(UnitCell *cell, gsl_matrix *rot, - struct rvec *a_star, struct rvec *b_star, - struct rvec *c_star) -{ - /* FIXME: more matrix stuff - multiply cell matrix by rotation matrix - * and extract the reciprocal axes from the definition of the matrix. - */ -} - /* ------------------------------------------------------------------------ * cleanup functions - called from run_taketwo(). * ------------------------------------------------------------------------*/ @@ -858,12 +850,11 @@ static void cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, * @rot: pointer to be given an assignment (hopefully) if indexing is * successful. **/ -int run_taketwo(UnitCell *cell, struct rvec *rlps, - int rlp_count, struct rvec *a_star, struct rvec *b_star, - struct rvec *c_star) +static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) { int cell_vec_count = 0; struct rvec *cell_vecs = NULL; + UnitCell *result; int success = 0; success = gen_theoretical_vecs(cell, &cell_vecs, &cell_vec_count); @@ -897,7 +888,7 @@ int run_taketwo(UnitCell *cell, struct rvec *rlps, find_seed_and_network(obs_vecs, obs_vec_count, &solution); - generate_basis_vectors(cell, solution, a_star, b_star, c_star); + result = transform_cell_gsl(cell, solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); -- cgit v1.2.3 From c4e633fa9dd70af035fe2edcab3825fd6c71c4e0 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:10:52 +0200 Subject: Final hooky bits --- libcrystfel/src/taketwo.c | 68 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index f3b9da5a..2befb8b5 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -36,6 +36,7 @@ #include "cell-utils.h" #include "index.h" #include "taketwo.h" +#include "peaks.h" /** * spotvec @@ -855,44 +856,32 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) int cell_vec_count = 0; struct rvec *cell_vecs = NULL; UnitCell *result; - - int success = 0; - success = gen_theoretical_vecs(cell, &cell_vecs, &cell_vec_count); - - if ( !success ) { - apologise(); - return 0; - } - int obs_vec_count = 0; struct SpotVec *obs_vecs = NULL; + int success = 0; + gsl_matrix *solution = NULL; - success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count); + success = gen_theoretical_vecs(cell, &cell_vecs, &cell_vec_count); + if ( !success ) return NULL; - if ( !success ) { - apologise(); - return 0; - } + success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count); + if ( !success ) return NULL; success = match_obs_to_cell_vecs(cell_vecs, cell_vec_count, obs_vecs, obs_vec_count); - if ( !success ) { - apologise(); - return 0; - } + if ( !success ) return NULL; cleanup_taketwo_cell_vecs(cell_vecs); - gsl_matrix *solution = NULL; - find_seed_and_network(obs_vecs, obs_vec_count, &solution); + if ( solution == NULL ) return NULL; result = transform_cell_gsl(cell, solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); - return (solution != NULL); + return result; } @@ -900,7 +889,44 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) int taketwo_index(struct image *image, IndexingPrivate *ipriv) { + Crystal *cr; + UnitCell *cell; + struct rvec *rlps; + int n_rlps = 0; + int i; struct taketwo_private *tp = (struct taketwo_private *)ipriv; + + rlps = malloc(image_feature_count(image->features)*sizeof(struct rvec)); + for ( i=0; ifeatures); i++ ) { + struct imagefeature *pk = image_get_feature(image->features, i); + if ( pk == NULL ) continue; + rlps[n_rlps].u = pk->rx; + rlps[n_rlps].v = pk->ry; + rlps[n_rlps].w = pk->rz; + n_rlps++; + } + + cell = run_taketwo(tp->cell, rlps, n_rlps); + if ( cell == NULL ) return 0; + + cr = crystal_new(); + if ( cr == NULL ) { + ERROR("Failed to allocate crystal.\n"); + return 0; + } + + crystal_set_cell(cr, cell); + + if ( tp->indm & INDEXING_CHECK_PEAKS ) { + if ( !peak_sanity_check(image, &cr, 1) ) { + cell_free(cell); + crystal_free(cr); + return 0; + } + } + + image_add_crystal(image, cr); + return 1; } -- cgit v1.2.3 From 4b1136b3cdb9b32126f908415af59bccaa9542ea Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:12:46 +0200 Subject: Fix iteration bounds --- libcrystfel/src/taketwo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 2befb8b5..b37123e4 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -714,8 +714,8 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, double max_sq_length = pow(MAX_RECIP_DISTANCE, 2); /* Indentation... bending the rules a bit? */ - for ( i=0; i Date: Wed, 19 Oct 2016 14:12:55 +0200 Subject: Formatting --- libcrystfel/src/taketwo.c | 53 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b37123e4..8b5fadbd 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -713,45 +713,44 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, /* maximum distance squared for comparisons */ double max_sq_length = pow(MAX_RECIP_DISTANCE, 2); - /* Indentation... bending the rules a bit? */ for ( i=0; i max_sq_length ) { - continue; - } + if ( sqlength > max_sq_length ) { + continue; + } - count++; + count++; - struct SpotVec *temp_obs_vecs; - temp_obs_vecs = realloc(*obs_vecs, - count*sizeof(struct SpotVec)); + struct SpotVec *temp_obs_vecs; + temp_obs_vecs = realloc(*obs_vecs, + count*sizeof(struct SpotVec)); - if ( temp_obs_vecs == NULL ) { - return 0; - } else { - *obs_vecs = temp_obs_vecs; + if ( temp_obs_vecs == NULL ) { + return 0; + } else { + *obs_vecs = temp_obs_vecs; - /* initialise all SpotVec struct members */ + /* initialise all SpotVec struct members */ - struct SpotVec spot_vec; - spot_vec.obsvec = diff; - spot_vec.distance = sqrt(sqlength); - spot_vec.matches = NULL; - spot_vec.match_num = 0; - spot_vec.her_rlp = &rlps[i]; - spot_vec.his_rlp = &rlps[j]; + struct SpotVec spot_vec; + spot_vec.obsvec = diff; + spot_vec.distance = sqrt(sqlength); + spot_vec.matches = NULL; + spot_vec.match_num = 0; + spot_vec.her_rlp = &rlps[i]; + spot_vec.his_rlp = &rlps[j]; - (*obs_vecs)[count - 1] = spot_vec; + (*obs_vecs)[count - 1] = spot_vec; + } } } - } *obs_vec_count = count; -- cgit v1.2.3 From f40d82f45579c0d23d577351acc23347d08d26e6 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:36:51 +0200 Subject: Fix units in constants --- libcrystfel/src/taketwo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 8b5fadbd..c84a2d8d 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -71,19 +71,19 @@ struct taketwo_private /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE 0.15 +#define MAX_RECIP_DISTANCE (0.15*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE 0.001 +#define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD 20 +#define NETWORK_MEMBER_THRESHOLD (20) /* Maximum network members (obviously a solution so should stop) */ -#define MAX_NETWORK_MEMBERS 100 +#define MAX_NETWORK_MEMBERS (100) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS 5 +#define MAX_DEAD_ENDS (5) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(1.0)) -- cgit v1.2.3 From 9211939e4cd21748fadbda519438e027ce654644 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:37:11 +0200 Subject: Fix maximum index determination --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index c84a2d8d..f87446fd 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -770,9 +770,9 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, cell_get_parameters(cell, &a, &b, &c, &alpha, &beta, &gamma); /* find maximum Miller (h, k, l) indices for a given resolution */ - h_max = MAX_RECIP_DISTANCE / a + 1; - k_max = MAX_RECIP_DISTANCE / b + 1; - l_max = MAX_RECIP_DISTANCE / c + 1; + h_max = MAX_RECIP_DISTANCE * a; + k_max = MAX_RECIP_DISTANCE * b; + l_max = MAX_RECIP_DISTANCE * c; int h, k, l; int count = 0; -- cgit v1.2.3 From d38bf1bc8a3924e796d4d934cd7999232585f281 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:37:28 +0200 Subject: Fix weird pointers --- libcrystfel/src/taketwo.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index f87446fd..7154c080 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -362,19 +362,17 @@ static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, - int *members[MAX_NETWORK_MEMBERS], int num) + int *members, int num) { int i; struct SpotVec *her_obs = &obs_vecs[test_idx]; for ( i=0; i Date: Wed, 19 Oct 2016 14:38:47 +0200 Subject: D'oh --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 7154c080..49a3c933 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -254,7 +254,7 @@ static double matrix_trace(gsl_matrix *a) double tr = 0.0; assert(a->size1 == a->size2); - for ( i=0; isize1; a++ ) { + for ( i=0; isize1; i++ ) { tr += gsl_matrix_get(a, i, i); } return tr; -- cgit v1.2.3 From c8029395ae91a4660efdae16b72c2e085ebf14d2 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 14:48:08 +0200 Subject: Default/required/optional flags for TakeTwo --- libcrystfel/src/index.h | 3 ++- libcrystfel/src/taketwo.c | 26 ++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h index 6ac9792a..23545506 100644 --- a/libcrystfel/src/index.h +++ b/libcrystfel/src/index.h @@ -58,8 +58,9 @@ | INDEXING_USE_CELL_PARAMETERS \ | INDEXING_RETRY | INDEXING_REFINE) -#define INDEXING_DEFAULTS_TAKETWO (INDEXING_TAKETWO \ +#define INDEXING_DEFAULTS_TAKETWO (INDEXING_TAKETWO | INDEXING_CHECK_PEAKS \ | INDEXING_USE_CELL_PARAMETERS \ + | INDEXING_USE_LATTICE_TYPE \ | INDEXING_RETRY | INDEXING_REFINE) /* Axis check is needed for XDS, because it likes to permute the axes */ diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 49a3c933..2ba72c91 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -927,22 +927,24 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, struct detector *det, float *ltl) { struct taketwo_private *tp; - int need_cell = 0; - if ( *indm & INDEXING_CHECK_CELL_COMBINATIONS ) need_cell = 1; - if ( *indm & INDEXING_CHECK_CELL_AXES ) need_cell = 1; + /* Flags that TakeTwo knows about */ + *indm &= INDEXING_METHOD_MASK | INDEXING_CHECK_PEAKS + | INDEXING_USE_LATTICE_TYPE | INDEXING_USE_CELL_PARAMETERS + | INDEXING_CONTROL_FLAGS; - if ( need_cell && !cell_has_parameters(cell) ) { - ERROR("Altering your TakeTwo flags because cell parameters were" - " not provided.\n"); - *indm &= ~INDEXING_CHECK_CELL_COMBINATIONS; - *indm &= ~INDEXING_CHECK_CELL_AXES; + if ( !( (*indm & INDEXING_USE_LATTICE_TYPE) + && (*indm & INDEXING_USE_CELL_PARAMETERS)) ) + { + ERROR("TakeTwo indexing requires cell and lattice type " + "information.\n"); + return NULL; } - /* Flags that TakeTwo knows about */ - *indm &= INDEXING_METHOD_MASK | INDEXING_CHECK_CELL_COMBINATIONS - | INDEXING_CHECK_CELL_AXES | INDEXING_CHECK_PEAKS - | INDEXING_CONTROL_FLAGS; + if ( cell == NULL ) { + ERROR("TakeTwo indexing requires a unit cell.\n"); + return NULL; + } tp = malloc(sizeof(struct taketwo_private)); if ( tp == NULL ) return NULL; -- cgit v1.2.3 From fa07eee6efd51a224a528f0d0fcc23c194c0fec0 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 15:30:29 +0200 Subject: Normalise the rotation axis --- libcrystfel/src/taketwo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 2ba72c91..0e999a0e 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -285,6 +285,7 @@ static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) { double th = rvec_angle(a, b); struct rvec c = rvec_cross(a, b); + normalise_rvec(&c); return rotation_around_axis(c, th); } -- cgit v1.2.3 From dc3a150fd217c58b9d1ab9107b9ba216801be090 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Wed, 19 Oct 2016 15:31:53 +0200 Subject: Minor cleanups --- libcrystfel/src/taketwo.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 0e999a0e..581c676d 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -465,18 +465,14 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int shared = obs_shares_spot_w_array(obs_vecs, i, members, member_num); - if ( !shared ) { - continue; - } + if ( !shared ) continue; /* now we check that angles between all vectors match */ int matches = obs_angles_match_array(obs_vecs, i, members, member_num); - if ( !matches ) { - continue; - } + if ( !matches ) continue; /* final test: does the corresponding rotation matrix * match the others? NOTE: have not tested to see if @@ -502,7 +498,7 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, */ int ok = 1; - for ( j=0; j<2 && ok; j++ ) { + for ( j=0; j<2; j++ ) { gsl_matrix *test_rot = gsl_matrix_calloc(3, 3); int j_idx = members[j]; @@ -512,11 +508,10 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, *test_match); ok = rot_mats_are_similar(rot, test_rot); + if ( !ok ) break; } - if ( !ok ) { - continue; - } + if ( !ok ) continue; /* successful branch - return to calling function...*/ @@ -548,9 +543,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int start = obs_idx2 + 1; while ( 1 ) { - /* There must be a better way of passing int *[100] pointer - * to an int ** parameter, but I don't know... - **/ + int next_index = find_next_index(rot, obs_vecs, obs_vec_count, members, start, member_num); -- cgit v1.2.3 From 8483ac19d1b6e30d4c17472cda59b74030c87db2 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Oct 2016 11:19:29 +0200 Subject: Formatting --- libcrystfel/src/taketwo.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 581c676d..52c95c06 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -385,8 +385,8 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, * cosine graph are more sensitive than others, so may be a trade off... or not. */ static int obs_vecs_match_angles(struct SpotVec *her_obs, - struct SpotVec *his_obs, int *her_match_idx, - int *his_match_idx) + struct SpotVec *his_obs, + int *her_match_idx, int *his_match_idx) { int i, j; @@ -468,7 +468,6 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if ( !shared ) continue; /* now we check that angles between all vectors match */ - int matches = obs_angles_match_array(obs_vecs, i, members, member_num); @@ -572,10 +571,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, member_num++; /* If member_num is high enough, we want to return a yes */ - - if ( member_num > NETWORK_MEMBER_THRESHOLD ) { - break; - } + if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } /* Deal with this shit after coffee */ @@ -601,26 +597,19 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, */ int shared = obs_vecs_share_spot(&obs_vecs[i], &obs_vecs[j]); - if ( !shared ) { - continue; - } + if ( !shared ) continue; /* cell vector "matches" index for i, j respectively */ int i_idx = -1; int j_idx = -1; /* Check to see if any angles match from the cell vectors */ - int match = 0; match = obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j], - &i_idx, &j_idx); - - if ( !match ) { - continue; - } + &i_idx, &j_idx); + if ( !match ) continue; /* We have a seed! Generate a matrix based on this solution */ - gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); rot_mat = generate_rot_mat(obs_vecs[i].obsvec, @@ -634,7 +623,6 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, i_idx, j_idx); /* return this matrix or free it and try again */ - if ( success ) { *rotation = rot_mat; return 1; @@ -709,9 +697,7 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, /* are these two far from each other? */ double sqlength = sq_length(diff); - if ( sqlength > max_sq_length ) { - continue; - } + if ( sqlength > max_sq_length ) continue; count++; -- cgit v1.2.3 From cea1984e5bbf5636ffc78ec1787f0ac5d1054476 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Oct 2016 11:19:57 +0200 Subject: Fix indices --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 52c95c06..bc27faf7 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -620,7 +620,7 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, /* try to expand this rotation matrix to a larger network */ int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i_idx, j_idx); + i, j); /* return this matrix or free it and try again */ if ( success ) { -- cgit v1.2.3 From 758bb13148341bfb288e550f25eac58df6a010e8 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Oct 2016 11:20:46 +0200 Subject: Add the central beam --- libcrystfel/src/taketwo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index bc27faf7..b9ba4ec6 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -868,7 +868,7 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) int i; struct taketwo_private *tp = (struct taketwo_private *)ipriv; - rlps = malloc(image_feature_count(image->features)*sizeof(struct rvec)); + rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); for ( i=0; ifeatures); i++ ) { struct imagefeature *pk = image_get_feature(image->features, i); if ( pk == NULL ) continue; @@ -877,6 +877,9 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) rlps[n_rlps].w = pk->rz; n_rlps++; } + rlps[n_rlps].u = 0.0; + rlps[n_rlps].v = 0.0; + rlps[n_rlps++].w = 0.0; cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From 3ea04ac6acc5b5fb3ab79286d9a303222a6c4cea Mon Sep 17 00:00:00 2001 From: cppxfel Date: Thu, 20 Oct 2016 11:36:51 +0200 Subject: Add tracking of cell match numbers to taketwo.c --- libcrystfel/src/taketwo.c | 51 ++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b9ba4ec6..04c60d7b 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -390,6 +390,9 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, { int i, j; + *her_match_idx = -1; + *his_match_idx = -1; + /* calculate angle between observed vectors */ double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); @@ -420,7 +423,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, - int *members, int num) + int *obs_members, int *match_members, int num) { /* note: this is just a preliminary check to reduce unnecessary * computation later down the line, but is not entirely accurate. @@ -432,7 +435,7 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, struct SpotVec *her_obs = &obs_vecs[test_idx]; for ( i=0; i Date: Thu, 20 Oct 2016 13:19:01 +0200 Subject: Vector fixes --- libcrystfel/src/taketwo.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 04c60d7b..f48b5ddc 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -180,7 +180,7 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) c.u = a.v*b.w - a.w*b.v; c.v = -(a.u*b.w - a.w*b.u); - c.w = a.u*b.v - a.v-b.u; + c.w = a.u*b.v - a.v*b.u; return c; } @@ -492,9 +492,7 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, &member_idx, &test_idx); *match_found = test_idx; - struct rvec *test_match = &obs_vecs[i].matches[test_idx]; - struct rvec *member_match; - member_match = &obs_vecs[obs_members[0]].matches[member_idx]; + struct rvec test_match = obs_vecs[i].matches[test_idx]; int j; @@ -504,13 +502,16 @@ static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int ok = 1; for ( j=0; j<2; j++ ) { - gsl_matrix *test_rot = gsl_matrix_calloc(3, 3); + gsl_matrix *test_rot = gsl_matrix_calloc(3, 3); + struct rvec member_match; int j_idx = obs_members[j]; + + member_match = obs_vecs[j].matches[match_members[j]]; test_rot = generate_rot_mat(obs_vecs[j_idx].obsvec, obs_vecs[i].obsvec, - *member_match, - *test_match); + member_match, + test_match); ok = rot_mats_are_similar(rot, test_rot); if ( !ok ) break; @@ -635,7 +636,7 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, /* try to expand this rotation matrix to a larger network */ int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j); + i, j, i_idx, j_idx); /* return this matrix or free it and try again */ if ( success ) { -- cgit v1.2.3 From eac1c202fd024d740fd8719e1fd5b99815dc036c Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Oct 2016 13:19:10 +0200 Subject: Set tolerance --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index f48b5ddc..bc41994d 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -74,7 +74,7 @@ struct taketwo_private #define MAX_RECIP_DISTANCE (0.15*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.001*1e10) +#define RECIP_TOLERANCE (0.0002*1e10) /* Threshold for network members to consider a potential solution */ #define NETWORK_MEMBER_THRESHOLD (20) -- cgit v1.2.3 From ea811692bee76479f27012c3bd2e73847fbef6b3 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Oct 2016 13:20:31 +0200 Subject: Fussiness --- libcrystfel/src/taketwo.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index bc41994d..1fdbd7c5 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -330,7 +330,7 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, normalise_rvec(&obs1); /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, + gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, 0.0, cell2vr); /* Now we twirl around the firstAxisUnit until the rotated simulated @@ -441,7 +441,6 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, int idx1, idx2; /* check our test vector matches existing network member */ - int matches = obs_vecs_match_angles(her_obs, his_obs, &idx1, &idx2); @@ -456,10 +455,10 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, * core functions regarding the meat of the TakeTwo algorithm (Level 2) * ------------------------------------------------------------------------*/ -static int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, - int obs_vec_count, int *obs_members, - int *match_members, int start, int member_num, - int *match_found) +static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, + int obs_vec_count, int *obs_members, + int *match_members, int start, int member_num, + int *match_found) { int i; @@ -555,7 +554,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, while ( 1 ) { int match_found = -1; - int next_index = find_next_index(rot, obs_vecs, obs_vec_count, + signed int next_index = find_next_index(rot, obs_vecs, obs_vec_count, obs_members, match_members, start, member_num, &match_found); -- cgit v1.2.3 From 0dd2f095933d7ef34ef4cbfa6354b7f3644a408e Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 24 Oct 2016 11:39:00 +0200 Subject: D'oh --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 1fdbd7c5..40e2fdf9 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -225,9 +225,9 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, /* Redeclaring these to try and maintain readability and * check-ability against the maths I wrote down */ - double a = vec2.u; double b = vec2.w; double c = vec2.v; - double p = vec1.u; double q = vec1.w; double r = vec1.v; - double x = axis.u; double y = axis.w; double z = axis.v; + double a = vec2.u; double b = vec2.v; double c = vec2.w; + double p = vec1.u; double q = vec1.v; double r = vec1.w; + double x = axis.u; double y = axis.v; double z = axis.w; /* Components in handwritten maths online when I upload it */ double A = a*(p*x*x - p + x*y*q + x*z*r) + -- cgit v1.2.3 From a2f6ba9952704e213b9a425fac5a6b848c6a78e5 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Mon, 24 Oct 2016 13:40:57 +0200 Subject: Separate tolerance for matrix trace --- libcrystfel/src/taketwo.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 40e2fdf9..7362a4c6 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -88,6 +88,9 @@ struct taketwo_private /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(1.0)) +/* Tolerance for rot_mats_are_similar */ +#define TRACE_TOLERANCE (deg2rad(8.0)) + /** TODO: * * - May need to be capable of playing with the tolerances/#defined stuff. @@ -277,7 +280,7 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) tr = matrix_trace(mul); gsl_matrix_free(mul); - return tr < sqrt(4.0*(1.0-cos(ANGLE_TOLERANCE)));; + return tr < sqrt(4.0*(1.0-cos(TRACE_TOLERANCE)));; } -- cgit v1.2.3 From 2679761cd4f86cf1829917a74c3f32ed5576a1d6 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 25 Oct 2016 17:44:04 +0200 Subject: Sort the vectors according to distance, and use a larger tolerance --- libcrystfel/src/taketwo.c | 63 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 7362a4c6..aa0491ab 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -74,7 +74,7 @@ struct taketwo_private #define MAX_RECIP_DISTANCE (0.15*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.0002*1e10) +#define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ #define NETWORK_MEMBER_THRESHOLD (20) @@ -654,6 +654,20 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, } +struct sortme +{ + struct rvec v; + double dist; +}; + +static int sort_func(const void *av, const void *bv) +{ + struct sortme *a = (struct sortme *)av; + struct sortme *b = (struct sortme *)bv; + return a->dist > b->dist; +} + + static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, struct SpotVec *obs_vecs, int obs_vec_count) { @@ -661,36 +675,41 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, /* Now I'm definitely bending the indentation rules! */ for ( i=0; i RECIP_TOLERANCE ) { - continue; - } + /* check if this matches the observed length */ + double dist_diff = fabs(cell_length - obs_length); - /* we have a match, add to array! */ + if ( dist_diff > RECIP_TOLERANCE ) continue; - count++; - int new_size = count*sizeof(struct rvec); - struct rvec *temp_matches; - temp_matches = realloc(obs_vecs[i].matches, new_size); + /* we have a match, add to array! */ + + size_t new_size = (count+1)*sizeof(struct sortme); + for_sort = realloc(for_sort, new_size); + + if ( for_sort == NULL ) return 0; + + for_sort[count].v = cell_vecs[j]; + for_sort[count].dist = dist_diff; + count++; - if ( temp_matches == NULL ) { - return 0; - } else { - obs_vecs[i].matches = temp_matches; - temp_matches[count - 1] = cell_vecs[j]; - obs_vecs[i].match_num = count; } - } + qsort(for_sort, count, sizeof(struct sortme), sort_func); + obs_vecs[i].matches = malloc(count*sizeof(struct rvec)); + for ( j=0; j Date: Tue, 25 Oct 2016 17:45:18 +0200 Subject: j_idx --- libcrystfel/src/taketwo.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index aa0491ab..036db5c6 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -509,7 +509,8 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, struct rvec member_match; int j_idx = obs_members[j]; - member_match = obs_vecs[j].matches[match_members[j]]; + member_match = obs_vecs[j_idx].matches[match_members[j]]; + test_rot = generate_rot_mat(obs_vecs[j_idx].obsvec, obs_vecs[i].obsvec, member_match, -- cgit v1.2.3 From 198bdddf99f1db5510dff63b7dc21d01cb98994a Mon Sep 17 00:00:00 2001 From: Thomas White Date: Tue, 25 Oct 2016 17:45:59 +0200 Subject: TEMPORARY horrible debugging stuff --- libcrystfel/src/cell-utils.c | 26 ++++---- libcrystfel/src/taketwo.c | 137 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 132 insertions(+), 31 deletions(-) diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c index 74a6b905..841d88f9 100644 --- a/libcrystfel/src/cell-utils.c +++ b/libcrystfel/src/cell-utils.c @@ -1445,27 +1445,33 @@ UnitCell *transform_cell_gsl(UnitCell *in, gsl_matrix *m) c = gsl_matrix_alloc(3, 3); gsl_matrix_set(c, 0, 0, asx); - gsl_matrix_set(c, 0, 1, asy); - gsl_matrix_set(c, 0, 2, asz); - gsl_matrix_set(c, 1, 0, bsx); + gsl_matrix_set(c, 1, 0, asy); + gsl_matrix_set(c, 2, 0, asz); + gsl_matrix_set(c, 0, 1, bsx); gsl_matrix_set(c, 1, 1, bsy); - gsl_matrix_set(c, 1, 2, bsz); - gsl_matrix_set(c, 2, 0, csx); - gsl_matrix_set(c, 2, 1, csy); + gsl_matrix_set(c, 2, 1, bsz); + gsl_matrix_set(c, 0, 2, csx); + gsl_matrix_set(c, 1, 2, csy); gsl_matrix_set(c, 2, 2, csz); + STATUS("---\n"); + show_matrix(m); + STATUS("\n"); + show_matrix(c); + STATUS("\n"); res = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, m, c, 0.0, res); + show_matrix(res); out = cell_new_from_cell(in); cell_set_reciprocal(out, gsl_matrix_get(res, 0, 0), - gsl_matrix_get(res, 0, 1), - gsl_matrix_get(res, 0, 2), gsl_matrix_get(res, 1, 0), - gsl_matrix_get(res, 1, 1), - gsl_matrix_get(res, 1, 2), gsl_matrix_get(res, 2, 0), + gsl_matrix_get(res, 0, 1), + gsl_matrix_get(res, 1, 1), gsl_matrix_get(res, 2, 1), + gsl_matrix_get(res, 0, 2), + gsl_matrix_get(res, 1, 2), gsl_matrix_get(res, 2, 2)); gsl_matrix_free(res); diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 036db5c6..9c173303 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -69,6 +69,9 @@ struct taketwo_private UnitCell *cell; }; +struct rvec *global_rlps; +int global_nrlps; + /* Maximum distance between two rlp sizes to consider info for indexing */ #define MAX_RECIP_DISTANCE (0.15*1e10) @@ -77,10 +80,10 @@ struct taketwo_private #define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (20) +#define NETWORK_MEMBER_THRESHOLD (500) /* Maximum network members (obviously a solution so should stop) */ -#define MAX_NETWORK_MEMBERS (100) +#define MAX_NETWORK_MEMBERS (500) /* Maximum dead ends for a single branch extension during indexing */ #define MAX_DEAD_ENDS (5) @@ -189,6 +192,12 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) } +static void show_rvec(struct rvec r) +{ + STATUS("[ %+9.3e %+9.3e %+9.3e ]\n", r.u, r.v, r.w); +} + + /* ------------------------------------------------------------------------ * functions called under the core functions, still specialised (Level 3) * ------------------------------------------------------------------------*/ @@ -326,9 +335,18 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_vector *cell2v = rvec_to_gsl(cell2); gsl_vector *cell2vr = gsl_vector_calloc(3); + STATUS("--\n"); + show_rvec(obs1); + show_rvec(obs2); + show_rvec(cell1); + show_rvec(cell2); + STATUS(".....\n"); + /* Rotate reciprocal space so that the first simulated vector lines up * with the observed vector. */ rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); + STATUS("rotateSpotDiffMatrix:\n"); + show_matrix(rotateSpotDiffMatrix); normalise_rvec(&obs1); @@ -338,14 +356,22 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Now we twirl around the firstAxisUnit until the rotated simulated * vector matches the second observed vector as closely as possible. */ - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), - obs2, obs1); + STATUS("for secondTwizzleMatrix:\n"); + show_rvec(gsl_to_rvec(cell2vr)); + show_rvec(obs2); + show_rvec(obs1); + STATUS("..\n"); + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); + STATUS("secondTwizzleMatrix:\n"); + show_matrix(secondTwizzleMatrix); /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ fullMat = gsl_matrix_calloc(3, 3); - gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, - secondTwizzleMatrix, rotateSpotDiffMatrix, 0.0, fullMat); + gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, + rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); + STATUS("final matrix:\n"); + show_matrix(fullMat); return fullMat; } @@ -448,6 +474,8 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, &idx1, &idx2); if (idx2 != match_members[i]) return 0; + //STATUS("match %i %i %i %i\n", idx1, idx2, test_idx, + // match_members[i]); } return 1; @@ -499,8 +527,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int j; /* if ok is set to 0, give up on this vector before - * checking the next value of j - */ + * thecking the next value of j */ int ok = 1; for ( j=0; j<2; j++ ) { @@ -510,6 +537,17 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int j_idx = obs_members[j]; member_match = obs_vecs[j_idx].matches[match_members[j]]; + STATUS("]]]]] %i %i %i %i\n", + j_idx, i, match_members[j], test_idx); + + //STATUS("test:\n"); + //struct rvec obs1 = {0, 1, 2}; + //struct rvec obs2 = {3, 4, 5}; + //struct rvec cell1 = {5, 7, 2}; + //struct rvec cell2 = {-1, 4, 3}; + //generate_rot_mat(obs1, obs2, cell1, cell2); + //STATUS("end of test\n"); + //exit(0); test_rot = generate_rot_mat(obs_vecs[j_idx].obsvec, obs_vecs[i].obsvec, @@ -517,6 +555,10 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, test_match); ok = rot_mats_are_similar(rot, test_rot); + //exit(0); + //STATUS("--\n"); + //show_matrix(rot); + STATUS("ok = %i\n", ok); if ( !ok ) break; } @@ -555,9 +597,12 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, /* we can start from after the 2nd observed vector in the seed */ int start = obs_idx2 + 1; + STATUS("starting..\n"); while ( 1 ) { int match_found = -1; + STATUS("member_num = %i\n", member_num); + signed int next_index = find_next_index(rot, obs_vecs, obs_vec_count, obs_members, match_members, start, member_num, @@ -585,7 +630,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, obs_members[member_num] = next_index; match_members[member_num] = match_found; - + start = next_index + 1; member_num++; @@ -599,6 +644,17 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } +static signed int spot_idx(struct rvec *rlp) +{ + int i; + for ( i=0; ifeatures)+1)*sizeof(struct rvec)); - for ( i=0; ifeatures); i++ ) { - struct imagefeature *pk = image_get_feature(image->features, i); - if ( pk == NULL ) continue; - rlps[n_rlps].u = pk->rx; - rlps[n_rlps].v = pk->ry; - rlps[n_rlps].w = pk->rz; - n_rlps++; + FILE *fh = fopen("../../spots.csv", "r"); + rlps = malloc(100*sizeof(struct rvec)); + while ( (fh != NULL) && !feof(fh) ) { + float x, y, z; + float dd; + int di; + char line[1024]; + fgets(line, 1024, fh); + + if ( sscanf(line, "%f,%f,%f,%f,%i,%i,%f,%f,%i", + &x, &y, &z, &dd, &di, &di, &dd, &dd, &di) == 9 ) { + if ( isnan(x) ) continue; + STATUS("got %f %f %f\n", x, y, z); + rlps[n_rlps].u = x*1e10; + rlps[n_rlps].v = y*1e10; + rlps[n_rlps].w = z*1e10; + n_rlps++; + } } rlps[n_rlps].u = 0.0; rlps[n_rlps].v = 0.0; rlps[n_rlps++].w = 0.0; + if ( fh != NULL ) fclose(fh); cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From 63b7677504ab543c408eaa24ec20f33f0cf687c7 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Fri, 4 Nov 2016 11:49:41 +0000 Subject: Fixes the bug I discovered in Hamburg - closest_rot_mat needs to check whether the theta angle is the minimum or maximum angle or whether to add Pi. --- libcrystfel/src/taketwo.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 9c173303..28a1a973 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -249,14 +249,36 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, double B = a*(y*r - z*q) + b*(p*z - r*x) + c*(q*x - p*y); double tan_theta = - B / A; + double theta = atan(tan_theta); - /* Not sure why I always have to take the + M_PI solution. Work - * this one out. But it always works!? */ - double theta = atan(tan_theta) + M_PI; + /* Now we have two possible solutions, theta or theta+pi + * and we need to work out which one. This could potentially be + * simplified - do we really need so many cos/sins? maybe check + * the 2nd derivative instead? */ + double cc = cos(theta); + double C = 1 - cc; + double s = sin(theta); + double occ = -cc; + double oC = 1 - occ; + double os = -s; + + double pPrime = (x*x*C+cc)*p + (x*y*C-z*s)*q + (x*z*C+y*s)*r; + double qPrime = (y*x*C+z*s)*p + (y*y*C+cc)*q + (y*z*C-x*s)*r; + double rPrime = (z*x*C-y*s)*p + (z*y*C+x*s)*q + (z*z*C+cc)*r; + + double pDbPrime = (x*x*oC+occ)*p + (x*y*oC-z*os)*q + (x*z*oC+y*os)*r; + double qDbPrime = (y*x*oC+z*os)*p + (y*y*oC+occ)*q + (y*z*oC-x*os)*r; + double rDbPrime = (z*x*oC-y*os)*p + (z*y*oC+x*os)*q + (z*z*oC+occ)*r; + + double cosAlpha = pPrime * a + qPrime * b + rPrime * c; + double cosAlphaOther = pDbPrime * a + qDbPrime * b + rDbPrime * c; + + int addPi = (cosAlphaOther > cosAlpha); + double bestAngle = theta + addPi * M_PI; /* Return an identity matrix which has been rotated by * theta around "axis" */ - return rotation_around_axis(axis, theta); + return rotation_around_axis(axis, bestAngle); } -- cgit v1.2.3 From 6a2ce6ae01f08fe0b0384f044a7919fc44d54ecb Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Fri, 11 Nov 2016 15:45:15 +0000 Subject: Find potential matches between observed and simulated vectors now returns a list, not a single match, in preparation for being more thorough searching --- libcrystfel/src/taketwo.c | 152 ++++++++++++++++++++++++---------------------- 1 file changed, 81 insertions(+), 71 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 28a1a973..07b05a6e 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -431,18 +431,21 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, } +// FIXME: decide if match count is returned or put in variable name /** Note: this could potentially (and cautiously) converted to comparing * cosines rather than angles, to lose an "acos" but different parts of the * cosine graph are more sensitive than others, so may be a trade off... or not. */ static int obs_vecs_match_angles(struct SpotVec *her_obs, struct SpotVec *his_obs, - int *her_match_idx, int *his_match_idx) + int **her_match_idxs, int **his_match_idxs, + int *match_count) { int i, j; + *match_count = 0; - *her_match_idx = -1; - *his_match_idx = -1; + // *her_match_idx = -1; + // *his_match_idx = -1; /* calculate angle between observed vectors */ double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); @@ -462,14 +465,31 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, double angle_diff = fabs(theory_angle - obs_angle); if ( angle_diff < ANGLE_TOLERANCE ) { - *her_match_idx = i; - *his_match_idx = j; - return 1; + + /* Reallocate the array to fit in another match */ + int *temp_hers; + temp_hers = realloc(her_match_idxs, *match_count * + sizeof(int)); + int *temp_his; + temp_his = realloc(his_match_idxs, *match_count * + sizeof(int)); + + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); + } + + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; + + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; + + (*match_count)++; } } } - return 0; + return (match_count > 0); } @@ -489,13 +509,16 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, struct SpotVec *his_obs = &obs_vecs[obs_members[i]]; /* placeholders, but results are ignored */ - int idx1, idx2; + int *idx1; + int *idx2; + int match_count; /* check our test vector matches existing network member */ - int matches = obs_vecs_match_angles(her_obs, his_obs, - &idx1, &idx2); + obs_vecs_match_angles(her_obs, his_obs, + &idx1, &idx2, &match_count); - if (idx2 != match_members[i]) return 0; + /* FIXME: this is going to be broken */ + // if (idx2 != match_members[i]) return 0; //STATUS("match %i %i %i %i\n", idx1, idx2, test_idx, // match_members[i]); } @@ -535,60 +558,47 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, * so for now, just sticking to the first two... */ - /* need to grab the matching vector index */ + /* need to grab all the matching vector indices */ - int member_idx, test_idx; + int *member_idx; + int *test_idx; + int match_num; /* FIXME: this may be a source of a problem */ obs_vecs_match_angles(&obs_vecs[obs_members[0]], &obs_vecs[i], - &member_idx, &test_idx); - - *match_found = test_idx; - struct rvec test_match = obs_vecs[i].matches[test_idx]; - - int j; + &member_idx, &test_idx, &match_num); /* if ok is set to 0, give up on this vector before - * thecking the next value of j */ - int ok = 1; - - for ( j=0; j<2; j++ ) { - - gsl_matrix *test_rot = gsl_matrix_calloc(3, 3); - struct rvec member_match; - int j_idx = obs_members[j]; - - member_match = obs_vecs[j_idx].matches[match_members[j]]; - STATUS("]]]]] %i %i %i %i\n", - j_idx, i, match_members[j], test_idx); - - //STATUS("test:\n"); - //struct rvec obs1 = {0, 1, 2}; - //struct rvec obs2 = {3, 4, 5}; - //struct rvec cell1 = {5, 7, 2}; - //struct rvec cell2 = {-1, 4, 3}; - //generate_rot_mat(obs1, obs2, cell1, cell2); - //STATUS("end of test\n"); - //exit(0); - - test_rot = generate_rot_mat(obs_vecs[j_idx].obsvec, - obs_vecs[i].obsvec, - member_match, - test_match); - - ok = rot_mats_are_similar(rot, test_rot); - //exit(0); - //STATUS("--\n"); - //show_matrix(rot); - STATUS("ok = %i\n", ok); - if ( !ok ) break; - } - - if ( !ok ) continue; - - /* successful branch - return to calling function...*/ - - return i; + * checking the next value of j */ + int j; + + for ( j=0; j Date: Fri, 11 Nov 2016 16:01:21 +0000 Subject: Send all possible seeds through the seed-starter --- libcrystfel/src/taketwo.c | 76 ++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 07b05a6e..1344d155 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -584,12 +584,12 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, // idx0, i, match_members[0], test_idx); /* Potential match with another vector */ - struct rvec test_match = obs_vecs[i].matches[test_idx[j]]; + struct rvec a_match = obs_vecs[i].matches[test_idx[j]]; test_rot = generate_rot_mat(obs_vecs[idx0].obsvec, obs_vecs[i].obsvec, member_match, - test_match); + a_match); int ok = rot_mats_are_similar(rot, test_rot); @@ -685,9 +685,40 @@ static signed int spot_idx(struct rvec *rlp) return -1; } +static int start_seed(struct SpotVec *obs_vecs, int i, int j, + int i_match, int j_match, gsl_matrix **rotation) +{ + gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); + + // FIXME: go through ALL matches, not jsut first + rot_mat = generate_rot_mat(obs_vecs[i].obsvec, + obs_vecs[j].obsvec, + obs_vecs[i].matches[i_match], + obs_vecs[j].matches[j_match]); + + /* Try to expand this rotation matrix to a larger network */ + STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", + i_match, j_match, i, j, + spot_idx(obs_vecs[i].her_rlp), + spot_idx(obs_vecs[i].his_rlp), + spot_idx(obs_vecs[j].her_rlp), + spot_idx(obs_vecs[j].his_rlp)); + show_matrix(rot_mat); + + int success = grow_network(rot_mat, obs_vecs, obs_vec_count, + i, j, i_match, j_match); + + /* return this matrix or free it and try again */ + if ( success ) { + *rotation = rot_mat; + return 1; + } else { + gsl_matrix_free(rot_mat); + return 0; + } +} - -static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, +static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, gsl_matrix **rotation) { /* loop round pairs of vectors to try and find a suitable @@ -718,33 +749,16 @@ static int find_seed_and_network(struct SpotVec *obs_vecs, int obs_vec_count, if ( matches == 0 ) continue; STATUS("...ok\n"); - /* We have a seed! Generate a matrix based on this solution */ - gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); - - // FIXME: go through ALL matches, not jsut first - rot_mat = generate_rot_mat(obs_vecs[i].obsvec, - obs_vecs[j].obsvec, - obs_vecs[i].matches[i_idx[0]], - obs_vecs[j].matches[j_idx[0]]); - - /* Try to expand this rotation matrix to a larger network */ - STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", - i_idx[0], j_idx[0], i, j, - spot_idx(obs_vecs[i].her_rlp), - spot_idx(obs_vecs[i].his_rlp), - spot_idx(obs_vecs[j].her_rlp), - spot_idx(obs_vecs[j].his_rlp)); - show_matrix(rot_mat); - int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_idx[0], j_idx[0]); - - /* return this matrix or free it and try again */ - if ( success ) { - *rotation = rot_mat; - return 1; - } else { - gsl_matrix_free(rot_mat); + /* We have seeds! Pass each of them through the seed-starter */ + int k; + for ( k=0; k Date: Fri, 11 Nov 2016 16:05:58 +0000 Subject: Fussiness --- libcrystfel/src/taketwo.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 1344d155..91fea28f 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -635,8 +635,9 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int match_found = -1; STATUS("member_num = %i\n", member_num); - signed int next_index = find_next_index(rot, obs_vecs, obs_vec_count, - obs_members, match_members, + signed int next_index = find_next_index(rot, obs_vecs, + obs_vec_count, obs_members, + match_members, start, member_num, &match_found); @@ -671,6 +672,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } /* Deal with this shit after coffee */ + /* (note: turns out there's no shit to deal with) */ return ( member_num > NETWORK_MEMBER_THRESHOLD ); } @@ -685,8 +687,8 @@ static signed int spot_idx(struct rvec *rlp) return -1; } -static int start_seed(struct SpotVec *obs_vecs, int i, int j, - int i_match, int j_match, gsl_matrix **rotation) +static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, + int j, int i_match, int j_match, gsl_matrix **rotation) { gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); @@ -752,7 +754,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, /* We have seeds! Pass each of them through the seed-starter */ int k; for ( k=0; k Date: Tue, 17 Jan 2017 10:41:14 +0000 Subject: Committing all newest antics which DOES produce a decent solution for a decent peak list... --- libcrystfel/src/taketwo.c | 215 +++++++++++++++++++++++++++++----------------- 1 file changed, 138 insertions(+), 77 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 91fea28f..ddad7cf7 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -74,25 +74,25 @@ int global_nrlps; /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.15*1e10) +#define MAX_RECIP_DISTANCE (0.1*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.001*1e10) +#define RECIP_TOLERANCE (0.00015*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (500) +#define NETWORK_MEMBER_THRESHOLD (25) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (500) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (5) +#define MAX_DEAD_ENDS (15) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(1.0)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(8.0)) +#define TRACE_TOLERANCE (deg2rad(7.0)) /** TODO: * @@ -194,7 +194,7 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) static void show_rvec(struct rvec r) { - STATUS("[ %+9.3e %+9.3e %+9.3e ]\n", r.u, r.v, r.w); + STATUS("[ %.3f %.3f %.3f ]\n", r.u, r.v, r.w); } @@ -310,8 +310,11 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) tr = matrix_trace(mul); gsl_matrix_free(mul); + double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); - return tr < sqrt(4.0*(1.0-cos(TRACE_TOLERANCE)));; + // STATUS("Trace is %.3f (max %.3f)\n", tr, max); + + return (tr < max); } @@ -349,7 +352,7 @@ struct rvec gsl_to_rvec(gsl_vector *a) * intensive on the number crunching side so simple angle checks are used * to 'pre-scan' vectors beforehand. */ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, - struct rvec cell1, struct rvec cell2) + struct rvec cell1, struct rvec cell2, int printDebug) { gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; @@ -357,18 +360,29 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_vector *cell2v = rvec_to_gsl(cell2); gsl_vector *cell2vr = gsl_vector_calloc(3); - STATUS("--\n"); - show_rvec(obs1); - show_rvec(obs2); - show_rvec(cell1); - show_rvec(cell2); - STATUS(".....\n"); + normalise_rvec(&obs1); + normalise_rvec(&obs2); + normalise_rvec(&cell1); + normalise_rvec(&cell2); + + if (0 && printDebug) + { + STATUS("--\n"); + show_rvec(obs1); + show_rvec(obs2); + show_rvec(cell1); + show_rvec(cell2); + STATUS(".....\n"); + } /* Rotate reciprocal space so that the first simulated vector lines up * with the observed vector. */ rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); - STATUS("rotateSpotDiffMatrix:\n"); - show_matrix(rotateSpotDiffMatrix); + if (printDebug) + { + // STATUS("rotateSpotDiffMatrix:\n"); + // show_matrix(rotateSpotDiffMatrix); + } normalise_rvec(&obs1); @@ -378,22 +392,27 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Now we twirl around the firstAxisUnit until the rotated simulated * vector matches the second observed vector as closely as possible. */ - STATUS("for secondTwizzleMatrix:\n"); - show_rvec(gsl_to_rvec(cell2vr)); - show_rvec(obs2); - show_rvec(obs1); - STATUS("..\n"); - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); - STATUS("secondTwizzleMatrix:\n"); - show_matrix(secondTwizzleMatrix); + + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); + + if (printDebug) + { + // STATUS("secondTwizzleMatrix:\n"); + // show_matrix(secondTwizzleMatrix); + } /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ fullMat = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); - STATUS("final matrix:\n"); - show_matrix(fullMat); + gsl_matrix_transpose(fullMat); + + if (printDebug) + { + STATUS("final matrix:\n"); + show_matrix(fullMat); + } return fullMat; } @@ -441,7 +460,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, int **her_match_idxs, int **his_match_idxs, int *match_count) { - int i, j; + int i, j; *match_count = 0; // *her_match_idx = -1; @@ -464,28 +483,30 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, double angle_diff = fabs(theory_angle - obs_angle); - if ( angle_diff < ANGLE_TOLERANCE ) { - - /* Reallocate the array to fit in another match */ - int *temp_hers; - temp_hers = realloc(her_match_idxs, *match_count * - sizeof(int)); - int *temp_his; - temp_his = realloc(his_match_idxs, *match_count * - sizeof(int)); - - if ( temp_hers == NULL || temp_his == NULL ) { - apologise(); - } - - (*her_match_idxs) = temp_hers; - (*his_match_idxs) = temp_his; - - (*her_match_idxs)[*match_count] = i; - (*his_match_idxs)[*match_count] = j; - + if ( angle_diff < ANGLE_TOLERANCE ) { + size_t new_size = (*match_count + 1) * + sizeof(int); + if (her_match_idxs && his_match_idxs) + { + /* Reallocate the array to fit in another match */ + int *temp_hers; + temp_hers = realloc(*her_match_idxs, new_size); + int *temp_his; + temp_his = realloc(*his_match_idxs, new_size); + + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); + } + + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; + + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; + } + (*match_count)++; - } + } } } @@ -509,13 +530,11 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, struct SpotVec *his_obs = &obs_vecs[obs_members[i]]; /* placeholders, but results are ignored */ - int *idx1; - int *idx2; - int match_count; + int match_count = 0; /* check our test vector matches existing network member */ obs_vecs_match_angles(her_obs, his_obs, - &idx1, &idx2, &match_count); + NULL, NULL, &match_count); /* FIXME: this is going to be broken */ // if (idx2 != match_members[i]) return 0; @@ -537,6 +556,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int *match_found) { int i; + // STATUS("Checking for next index from start=%i, max %i\n", start, obs_vec_count); for ( i=start; i obs_vec_count) { + STATUS("Reached end of observed vectors.\n"); + return -1; + } + int match_found = -1; + signed int next_index = find_next_index(rot, obs_vecs, obs_vec_count, obs_members, match_members, start, member_num, &match_found); + // STATUS("Next index is %i, match is %i\n", next_index, match_found); - if ( member_num < 2 ) return 0; + if ( member_num < 2 ) { + STATUS("giving up on seed..\n"); + return 0; + } if ( next_index < 0 ) { - /* If there have been too many dead ends, give up + STATUS("dead end number %i..\n", dead_ends); + /* If there have been too many dead ends, give up * on indexing altogether. **/ - if ( dead_ends > MAX_DEAD_ENDS ) break; + if ( dead_ends > MAX_DEAD_ENDS ) { + STATUS("Too many dead ends!\n"); + dead_ends = 0; + continue; + } /* We have not had too many dead ends. Try removing the last member and continue. */ - start = obs_members[member_num - 1] + 1; + start++; member_num--; dead_ends++; + STATUS("Shaving back one.\n"); continue; } /* we have elongated membership - so reset dead_ends counter */ - dead_ends = 0; + // dead_ends = 0; obs_members[member_num] = next_index; match_members[member_num] = match_found; start = next_index + 1; member_num++; - + STATUS("elongating seed, now %i members. They are: ", member_num); + int c; + for (c = 0; c < member_num; c++) { + STATUS("%i, ", obs_members[c]); + } + + STATUS("\n"); + /* If member_num is high enough, we want to return a yes */ if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } @@ -690,13 +737,14 @@ static signed int spot_idx(struct rvec *rlp) static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, int j, int i_match, int j_match, gsl_matrix **rotation) { - gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); + STATUS("starting new seed for obsvs %i and %i..\n", i, j); + gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); // FIXME: go through ALL matches, not jsut first rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], - obs_vecs[j].matches[j_match]); + obs_vecs[j].matches[j_match], 1); /* Try to expand this rotation matrix to a larger network */ STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", @@ -741,21 +789,21 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, if ( !shared ) continue; /* cell vector "matches" index for i, j respectively */ - int *i_idx; - int *j_idx; + int *i_idx = 0; + int *j_idx = 0; int matches; /* Check to see if any angles match from the cell vectors */ obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j], &i_idx, &j_idx, &matches); if ( matches == 0 ) continue; - STATUS("...ok\n"); + STATUS("...ok, %i matches\n", matches); /* We have seeds! Pass each of them through the seed-starter */ int k; for ( k=0; k max_sq_length ) continue; + STATUS("obs %i (spots %i and %i)", count, i, j); + struct rvec norm = new_rvec(diff.u, diff.v, diff.w); + normalise_rvec(&norm); + show_rvec(norm); count++; @@ -1021,6 +1073,15 @@ global_nrlps = rlp_count; find_seed(obs_vecs, obs_vec_count, &solution); if ( solution == NULL ) return NULL; + double x0 = gsl_matrix_get(solution, 0, 0); + gsl_matrix_set(solution, 0, 0, -x0); + + double x1 = gsl_matrix_get(solution, 0, 1); + gsl_matrix_set(solution, 0, 1, -x1); + + double x2 = gsl_matrix_get(solution, 0, 2); + gsl_matrix_set(solution, 0, 2, -x2); + result = transform_cell_gsl(cell, solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); @@ -1040,7 +1101,7 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) struct taketwo_private *tp = (struct taketwo_private *)ipriv; FILE *fh = fopen("../../spots.csv", "r"); - rlps = malloc(100*sizeof(struct rvec)); + rlps = malloc(500*sizeof(struct rvec)); while ( (fh != NULL) && !feof(fh) ) { float x, y, z; float dd; -- cgit v1.2.3 From 479077487c65a1e4264a28019c9079d00f00d8c6 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 13:30:47 +0000 Subject: Add rlp retrieval from peak list and tidy up the output to the screen a tad --- libcrystfel/src/taketwo.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index ddad7cf7..2c6b4f06 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -86,13 +86,13 @@ int global_nrlps; #define MAX_NETWORK_MEMBERS (500) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (15) +#define MAX_DEAD_ENDS (10) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(1.0)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(7.0)) +#define TRACE_TOLERANCE (deg2rad(4.0)) /** TODO: * @@ -617,10 +617,10 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if (ok) { - generate_rot_mat(obs_vecs[idx0].obsvec, + /* generate_rot_mat(obs_vecs[idx0].obsvec, obs_vecs[i].obsvec, member_match, - a_match, 1); + a_match, 0);*/ *match_found = j; return i; } @@ -678,12 +678,10 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } if ( next_index < 0 ) { - STATUS("dead end number %i..\n", dead_ends); - /* If there have been too many dead ends, give up + /* If there have been too many dead ends, give up * on indexing altogether. **/ if ( dead_ends > MAX_DEAD_ENDS ) { - STATUS("Too many dead ends!\n"); dead_ends = 0; continue; } @@ -693,7 +691,6 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, start++; member_num--; dead_ends++; - STATUS("Shaving back one.\n"); continue; } @@ -744,7 +741,7 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], - obs_vecs[j].matches[j_match], 1); + obs_vecs[j].matches[j_match], 0); /* Try to expand this rotation matrix to a larger network */ STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", @@ -801,7 +798,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, /* We have seeds! Pass each of them through the seed-starter */ int k; - for ( k=0; k max_sq_length ) continue; - STATUS("obs %i (spots %i and %i)", count, i, j); - struct rvec norm = new_rvec(diff.u, diff.v, diff.w); - normalise_rvec(&norm); - show_rvec(norm); - +// STATUS("obs %i (spots %i and %i)", count, i, j); + count++; struct SpotVec *temp_obs_vecs; @@ -1098,8 +1092,23 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) UnitCell *cell; struct rvec *rlps; int n_rlps = 0; + int i; struct taketwo_private *tp = (struct taketwo_private *)ipriv; + rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); + for ( i=0; ifeatures); i++ ) { + struct imagefeature *pk = image_get_feature(image->features, i); + if ( pk == NULL ) continue; + rlps[n_rlps].u = pk->rx; + rlps[n_rlps].v = pk->ry; + rlps[n_rlps].w = pk->rz; + n_rlps++; + } + rlps[n_rlps].u = 0.0; + rlps[n_rlps].v = 0.0; + rlps[n_rlps++].w = 0.0; + +/* FILE *fh = fopen("../../spots.csv", "r"); rlps = malloc(500*sizeof(struct rvec)); while ( (fh != NULL) && !feof(fh) ) { @@ -1122,7 +1131,8 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) rlps[n_rlps].u = 0.0; rlps[n_rlps].v = 0.0; rlps[n_rlps++].w = 0.0; - if ( fh != NULL ) fclose(fh); + + if ( fh != NULL ) fclose(fh);*/ cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From a1cbad95de010b8e75eda82dfd15c40170574e9c Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 14:40:56 +0000 Subject: Remove flip required for cppxfel coordinate system --- libcrystfel/src/taketwo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 2c6b4f06..4ee67767 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1066,7 +1066,7 @@ global_nrlps = rlp_count; find_seed(obs_vecs, obs_vec_count, &solution); if ( solution == NULL ) return NULL; - +/* double x0 = gsl_matrix_get(solution, 0, 0); gsl_matrix_set(solution, 0, 0, -x0); @@ -1074,7 +1074,7 @@ global_nrlps = rlp_count; gsl_matrix_set(solution, 0, 1, -x1); double x2 = gsl_matrix_get(solution, 0, 2); - gsl_matrix_set(solution, 0, 2, -x2); + gsl_matrix_set(solution, 0, 2, -x2);*/ result = transform_cell_gsl(cell, solution); -- cgit v1.2.3 From e43cd9c4dc57c5aedcebf02a6e78d961928951d9 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 14:45:05 +0000 Subject: Fiddle with parameter - temporary --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 4ee67767..a1b7f8c7 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -80,7 +80,7 @@ int global_nrlps; #define RECIP_TOLERANCE (0.00015*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (25) +#define NETWORK_MEMBER_THRESHOLD (11) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (500) -- cgit v1.2.3 From 743f8019286e7f68bd7c88580673ef7ccd63e3a8 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 14:53:50 +0000 Subject: Fiddles with parameters - more sensible now --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index a1b7f8c7..52540d15 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -74,13 +74,13 @@ int global_nrlps; /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.1*1e10) +#define MAX_RECIP_DISTANCE (0.12*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ #define RECIP_TOLERANCE (0.00015*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (11) +#define NETWORK_MEMBER_THRESHOLD (30) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (500) @@ -92,7 +92,7 @@ int global_nrlps; #define ANGLE_TOLERANCE (deg2rad(1.0)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(4.0)) +#define TRACE_TOLERANCE (deg2rad(8.0)) /** TODO: * -- cgit v1.2.3 From 1db7d84152ecd8cea4922cabb9db725943f83151 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 15:15:29 +0000 Subject: General beginning of tidying and removing some debug statements and return best solution if they're all too rubbish to hit the threshold - not tested --- libcrystfel/src/taketwo.c | 163 ++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 99 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 52540d15..b5604d1a 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -352,7 +352,7 @@ struct rvec gsl_to_rvec(gsl_vector *a) * intensive on the number crunching side so simple angle checks are used * to 'pre-scan' vectors beforehand. */ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, - struct rvec cell1, struct rvec cell2, int printDebug) + struct rvec cell1, struct rvec cell2) { gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; @@ -360,46 +360,25 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_vector *cell2v = rvec_to_gsl(cell2); gsl_vector *cell2vr = gsl_vector_calloc(3); - normalise_rvec(&obs1); - normalise_rvec(&obs2); - normalise_rvec(&cell1); - normalise_rvec(&cell2); - - if (0 && printDebug) - { - STATUS("--\n"); - show_rvec(obs1); - show_rvec(obs2); - show_rvec(cell1); - show_rvec(cell2); - STATUS(".....\n"); - } + normalise_rvec(&obs1); + normalise_rvec(&obs2); + normalise_rvec(&cell1); + normalise_rvec(&cell2); - /* Rotate reciprocal space so that the first simulated vector lines up - * with the observed vector. */ - rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); - if (printDebug) - { - // STATUS("rotateSpotDiffMatrix:\n"); - // show_matrix(rotateSpotDiffMatrix); - } + /* Rotate reciprocal space so that the first simulated vector lines up + * with the observed vector. */ + rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); - normalise_rvec(&obs1); + normalise_rvec(&obs1); - /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, - 0.0, cell2vr); + /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ + gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, + 0.0, cell2vr); - /* Now we twirl around the firstAxisUnit until the rotated simulated - * vector matches the second observed vector as closely as possible. */ + /* Now we twirl around the firstAxisUnit until the rotated simulated + * vector matches the second observed vector as closely as possible. */ - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); - - if (printDebug) - { - // STATUS("secondTwizzleMatrix:\n"); - // show_matrix(secondTwizzleMatrix); - } + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ @@ -407,12 +386,6 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); gsl_matrix_transpose(fullMat); - - if (printDebug) - { - STATUS("final matrix:\n"); - show_matrix(fullMat); - } return fullMat; } @@ -611,16 +584,12 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, test_rot = generate_rot_mat(obs_vecs[idx0].obsvec, obs_vecs[i].obsvec, member_match, - a_match, 0); + a_match); int ok = rot_mats_are_similar(rot, test_rot); if (ok) { - /* generate_rot_mat(obs_vecs[idx0].obsvec, - obs_vecs[i].obsvec, - member_match, - a_match, 0);*/ *match_found = j; return i; } @@ -635,11 +604,12 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int obs_vec_count, int obs_idx1, int obs_idx2, - int match_idx1, int match_idx2) + int match_idx1, int match_idx2, int *max_members, + int accept_anything) { /* indices of members of the self-consistent network of vectors */ int obs_members[MAX_NETWORK_MEMBERS]; - int match_members[MAX_NETWORK_MEMBERS]; + int match_members[MAX_NETWORK_MEMBERS]; /* initialise the ones we know already */ obs_members[0] = obs_idx1; @@ -703,6 +673,11 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, start = next_index + 1; member_num++; + + if (member_num > *max_members) { + *max_members = member_num; + } + STATUS("elongating seed, now %i members. They are: ", member_num); int c; for (c = 0; c < member_num; c++) { @@ -732,7 +707,8 @@ static signed int spot_idx(struct rvec *rlp) } static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, - int j, int i_match, int j_match, gsl_matrix **rotation) + int j, int i_match, int j_match, gsl_matrix **rotation, + int *max_members, int accept_anything) { STATUS("starting new seed for obsvs %i and %i..\n", i, j); gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); @@ -741,7 +717,7 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], - obs_vecs[j].matches[j_match], 0); + obs_vecs[j].matches[j_match]); /* Try to expand this rotation matrix to a larger network */ STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", @@ -753,7 +729,8 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, show_matrix(rot_mat); int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_match, j_match); + i, j, i_match, j_match, max_members, + accept_anything); /* return this matrix or free it and try again */ if ( success ) { @@ -766,13 +743,17 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, } static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, - gsl_matrix **rotation) + gsl_matrix **rotation) { + /* META: Maximum achieved maximum network membership */ + int max_max_members = 0; + int best_i, best_j, best_i_idx, best_j_idx; + /* loop round pairs of vectors to try and find a suitable * seed to start building a self-consistent network of vectors */ int i, j; - + for ( i=0; i max_max_members) { + max_max_members = max_members; + best_i = i; + best_j = j; + best_i_idx = i_idx[k]; + best_j_idx = j_idx[k]; + } + } } } } /* yes this } is meant to be here */ - return 0; + int max_members = 0; + int success = start_seed(obs_vecs, obs_vec_count, best_i, best_j, + best_i_idx, best_j_idx, + rotation, &max_members, + 1); + + if (success) { + return success; + } else { + /* Well, shit... something went wrong. */ + return 0; + } } @@ -873,12 +879,6 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, obs_vecs[i].match_num = count; for ( j=0; jcell, rlps, n_rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From 3e463696b41f01665535cd1a9740ca5e630a8e4f Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 15:28:26 +0000 Subject: Removed all debug messages, nice and clean. --- libcrystfel/src/cell-utils.c | 6 -- libcrystfel/src/taketwo.c | 191 ++++++++++++++++--------------------------- 2 files changed, 72 insertions(+), 125 deletions(-) diff --git a/libcrystfel/src/cell-utils.c b/libcrystfel/src/cell-utils.c index 841d88f9..8fa3b894 100644 --- a/libcrystfel/src/cell-utils.c +++ b/libcrystfel/src/cell-utils.c @@ -1454,14 +1454,8 @@ UnitCell *transform_cell_gsl(UnitCell *in, gsl_matrix *m) gsl_matrix_set(c, 1, 2, csy); gsl_matrix_set(c, 2, 2, csz); - STATUS("---\n"); - show_matrix(m); - STATUS("\n"); - show_matrix(c); - STATUS("\n"); res = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, m, c, 0.0, res); - show_matrix(res); out = cell_new_from_cell(in); cell_set_reciprocal(out, gsl_matrix_get(res, 0, 0), diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b5604d1a..b7f117ea 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -310,11 +310,9 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) tr = matrix_trace(mul); gsl_matrix_free(mul); - double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); + double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); - // STATUS("Trace is %.3f (max %.3f)\n", tr, max); - - return (tr < max); + return (tr < max); } @@ -456,30 +454,30 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, double angle_diff = fabs(theory_angle - obs_angle); - if ( angle_diff < ANGLE_TOLERANCE ) { - size_t new_size = (*match_count + 1) * - sizeof(int); - if (her_match_idxs && his_match_idxs) - { - /* Reallocate the array to fit in another match */ - int *temp_hers; - temp_hers = realloc(*her_match_idxs, new_size); - int *temp_his; - temp_his = realloc(*his_match_idxs, new_size); + if ( angle_diff < ANGLE_TOLERANCE ) { + size_t new_size = (*match_count + 1) * + sizeof(int); + if (her_match_idxs && his_match_idxs) + { + /* Reallocate the array to fit in another match */ + int *temp_hers; + temp_hers = realloc(*her_match_idxs, new_size); + int *temp_his; + temp_his = realloc(*his_match_idxs, new_size); - if ( temp_hers == NULL || temp_his == NULL ) { - apologise(); - } + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); + } - (*her_match_idxs) = temp_hers; - (*his_match_idxs) = temp_his; + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; - (*her_match_idxs)[*match_count] = i; - (*his_match_idxs)[*match_count] = j; - } + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; + } - (*match_count)++; - } + (*match_count)++; + } } } @@ -503,16 +501,12 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, struct SpotVec *his_obs = &obs_vecs[obs_members[i]]; /* placeholders, but results are ignored */ - int match_count = 0; + int match_count = 0; /* check our test vector matches existing network member */ obs_vecs_match_angles(her_obs, his_obs, NULL, NULL, &match_count); - /* FIXME: this is going to be broken */ - // if (idx2 != match_members[i]) return 0; - //STATUS("match %i %i %i %i\n", idx1, idx2, test_idx, - // match_members[i]); } return 1; @@ -529,8 +523,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int *match_found) { int i; - // STATUS("Checking for next index from start=%i, max %i\n", start, obs_vec_count); - + for ( i=start; i obs_vec_count) { - STATUS("Reached end of observed vectors.\n"); - return -1; - } + if (start > obs_vec_count) { + return -1; + } - int match_found = -1; - - signed int next_index = find_next_index(rot, obs_vecs, - obs_vec_count, obs_members, - match_members, - start, member_num, - &match_found); - // STATUS("Next index is %i, match is %i\n", next_index, match_found); - - if ( member_num < 2 ) { - STATUS("giving up on seed..\n"); - return 0; - } + int match_found = -1; + + signed int next_index = find_next_index(rot, obs_vecs, + obs_vec_count, obs_members, + match_members, + start, member_num, + &match_found); - if ( next_index < 0 ) { - /* If there have been too many dead ends, give up - * on indexing altogether. - **/ - if ( dead_ends > MAX_DEAD_ENDS ) { - dead_ends = 0; - continue; - } + if ( member_num < 2 ) { + return 0; + } - /* We have not had too many dead ends. Try removing - the last member and continue. */ - start++; - member_num--; - dead_ends++; + if ( next_index < 0 ) { + /* If there have been too many dead ends, give up + * on indexing altogether. + **/ + if ( dead_ends > MAX_DEAD_ENDS ) { + dead_ends = 0; + continue; + } - continue; - } + /* We have not had too many dead ends. Try removing + the last member and continue. */ + start++; + member_num--; + dead_ends++; - /* we have elongated membership - so reset dead_ends counter */ - // dead_ends = 0; + continue; + } - obs_members[member_num] = next_index; - match_members[member_num] = match_found; + /* we have elongated membership - so reset dead_ends counter */ + // dead_ends = 0; - start = next_index + 1; - member_num++; - - if (member_num > *max_members) { - *max_members = member_num; - } - - STATUS("elongating seed, now %i members. They are: ", member_num); - int c; - for (c = 0; c < member_num; c++) { - STATUS("%i, ", obs_members[c]); - } + obs_members[member_num] = next_index; + match_members[member_num] = match_found; + + start = next_index + 1; + member_num++; - STATUS("\n"); - - /* If member_num is high enough, we want to return a yes */ - if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; + if (member_num > *max_members) { + *max_members = member_num; + } + + /* If member_num is high enough, we want to return a yes */ + if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } /* Deal with this shit after coffee */ @@ -710,8 +686,7 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, int j, int i_match, int j_match, gsl_matrix **rotation, int *max_members, int accept_anything) { - STATUS("starting new seed for obsvs %i and %i..\n", i, j); - gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); + gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); // FIXME: go through ALL matches, not jsut first rot_mat = generate_rot_mat(obs_vecs[i].obsvec, @@ -720,14 +695,7 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, obs_vecs[j].matches[j_match]); /* Try to expand this rotation matrix to a larger network */ - STATUS("idx: %i %i %i %i spots %i %i and %i %i\n", - i_match, j_match, i, j, - spot_idx(obs_vecs[i].her_rlp), - spot_idx(obs_vecs[i].his_rlp), - spot_idx(obs_vecs[j].her_rlp), - spot_idx(obs_vecs[j].his_rlp)); - show_matrix(rot_mat); - + int success = grow_network(rot_mat, obs_vecs, obs_vec_count, i, j, i_match, j_match, max_members, accept_anything); @@ -762,8 +730,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, * by spot instead of by vector. */ int shared = obs_vecs_share_spot(&obs_vecs[i], &obs_vecs[j]); - //STATUS("checking %i %i\n", i, j); - + if ( !shared ) continue; /* cell vector "matches" index for i, j respectively */ @@ -775,8 +742,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j], &i_idx, &j_idx, &matches); if ( matches == 0 ) continue; - STATUS("...ok, %i matches\n", matches); - + /* We have seeds! Pass each of them through the seed-starter */ /* If a seed has the highest achieved membership, make note...*/ int k; @@ -843,11 +809,6 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, int count = 0; struct sortme *for_sort = NULL; - if ( (i==0) || (i==1) || (i==2) ) { - STATUS("length of %i = %f\n", i, - obs_vecs[i].distance/1e10); - } - for ( j=0; j max_sq_length ) continue; -// STATUS("obs %i (spots %i and %i)", count, i, j); count++; @@ -1047,16 +1003,13 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) success = gen_theoretical_vecs(cell, &cell_vecs, &cell_vec_count); if ( !success ) return NULL; - STATUS("cell_vec_count = %i\n", cell_vec_count); global_rlps = rlps; global_nrlps = rlp_count; success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count); if ( !success ) return NULL; - STATUS("obs_vec_count = %i\n", obs_vec_count); - STATUS("rlp_count = %i\n", rlp_count); - + success = match_obs_to_cell_vecs(cell_vecs, cell_vec_count, obs_vecs, obs_vec_count); -- cgit v1.2.3 From 180fcf419cc9aa4fd1bb4d5e483ddfa21d9c4de4 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Tue, 17 Jan 2017 15:33:57 +0000 Subject: Random indentation plus faffing with parameters. --- libcrystfel/src/taketwo.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b7f117ea..028847ac 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -74,13 +74,13 @@ int global_nrlps; /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.12*1e10) +#define MAX_RECIP_DISTANCE (0.15*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.00015*1e10) +#define RECIP_TOLERANCE (0.0002*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (30) +#define NETWORK_MEMBER_THRESHOLD (50) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (500) @@ -1039,18 +1039,18 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) int i; struct taketwo_private *tp = (struct taketwo_private *)ipriv; - rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); - for ( i=0; ifeatures); i++ ) { + rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); + for ( i=0; ifeatures); i++ ) { struct imagefeature *pk = image_get_feature(image->features, i); if ( pk == NULL ) continue; rlps[n_rlps].u = pk->rx; rlps[n_rlps].v = pk->ry; rlps[n_rlps].w = pk->rz; n_rlps++; - } - rlps[n_rlps].u = 0.0; - rlps[n_rlps].v = 0.0; - rlps[n_rlps++].w = 0.0; + } + rlps[n_rlps].u = 0.0; + rlps[n_rlps].v = 0.0; + rlps[n_rlps++].w = 0.0; cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From 4d8c846f2853ffa85c170c3e0aca5506e9c6a9a2 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 12:59:39 +0000 Subject: Fiddled with parameters, now nice for CPV17. Fixed a ton of bugs too --- libcrystfel/src/taketwo.c | 253 ++++++++++++++++++++++++++++++---------------- 1 file changed, 168 insertions(+), 85 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 028847ac..7e545fd2 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -37,6 +38,7 @@ #include "index.h" #include "taketwo.h" #include "peaks.h" +#include /** * spotvec @@ -74,25 +76,25 @@ int global_nrlps; /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.15*1e10) +#define MAX_RECIP_DISTANCE (0.12*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.0002*1e10) +#define RECIP_TOLERANCE (0.0005*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (50) +#define NETWORK_MEMBER_THRESHOLD (20) /* Maximum network members (obviously a solution so should stop) */ -#define MAX_NETWORK_MEMBERS (500) +#define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 5) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (10) +#define MAX_DEAD_ENDS (5) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(1.0)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(8.0)) +#define TRACE_TOLERANCE (deg2rad(3.0)) /** TODO: * @@ -192,8 +194,10 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) } -static void show_rvec(struct rvec r) +static void show_rvec(struct rvec r2) { + struct rvec r = r2; + normalise_rvec(&r); STATUS("[ %.3f %.3f %.3f ]\n", r.u, r.v, r.w); } @@ -295,7 +299,8 @@ static double matrix_trace(gsl_matrix *a) } -static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) +static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, + double *score) { double tr; gsl_matrix *sub; @@ -309,6 +314,8 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2) gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, sub, sub, 0.0, mul); tr = matrix_trace(mul); + if (score != NULL) *score = tr; + gsl_matrix_free(mul); double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); @@ -464,24 +471,24 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, temp_hers = realloc(*her_match_idxs, new_size); int *temp_his; temp_his = realloc(*his_match_idxs, new_size); - + if ( temp_hers == NULL || temp_his == NULL ) { apologise(); } (*her_match_idxs) = temp_hers; (*his_match_idxs) = temp_his; - + (*her_match_idxs)[*match_count] = i; (*his_match_idxs)[*match_count] = j; } - (*match_count)++; + (*match_count)++; } } } - return (match_count > 0); + return (*match_count > 0); } @@ -494,7 +501,7 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, * is identical - too much faff. **/ - int i; + int i, j; struct SpotVec *her_obs = &obs_vecs[test_idx]; for ( i=0; i obs_vec_count) { - return -1; + return 0; } int match_found = -1; @@ -625,7 +702,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, obs_vec_count, obs_members, match_members, start, member_num, - &match_found); + &match_found, 0); if ( member_num < 2 ) { return 0; @@ -636,8 +713,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, * on indexing altogether. **/ if ( dead_ends > MAX_DEAD_ENDS ) { - dead_ends = 0; - continue; + break; } /* We have not had too many dead ends. Try removing @@ -650,7 +726,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } /* we have elongated membership - so reset dead_ends counter */ - // dead_ends = 0; + dead_ends = 0; obs_members[member_num] = next_index; match_members[member_num] = match_found; @@ -666,8 +742,8 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } - /* Deal with this shit after coffee */ - /* (note: turns out there's no shit to deal with) */ + finalise_solution(rot, obs_vecs, obs_members, + match_members, member_num); return ( member_num > NETWORK_MEMBER_THRESHOLD ); } @@ -684,11 +760,10 @@ static signed int spot_idx(struct rvec *rlp) static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, int j, int i_match, int j_match, gsl_matrix **rotation, - int *max_members, int accept_anything) + int *max_members) { gsl_matrix *rot_mat = gsl_matrix_calloc(3, 3); - // FIXME: go through ALL matches, not jsut first rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], @@ -697,17 +772,12 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, /* Try to expand this rotation matrix to a larger network */ int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_match, j_match, max_members, - accept_anything); - - /* return this matrix or free it and try again */ - if ( success ) { - *rotation = rot_mat; - return 1; - } else { - gsl_matrix_free(rot_mat); - return 0; - } + i, j, i_match, j_match, max_members); + + /* return this matrix and if it was immediately successful */ + *rotation = rot_mat; + + return success; } static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, @@ -715,7 +785,9 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, { /* META: Maximum achieved maximum network membership */ int max_max_members = 0; - int best_i, best_j, best_i_idx, best_j_idx; + gsl_matrix *best_rotation = NULL; + + unsigned long start_time = time(NULL); /* loop round pairs of vectors to try and find a suitable * seed to start building a self-consistent network of vectors @@ -746,42 +818,43 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, /* We have seeds! Pass each of them through the seed-starter */ /* If a seed has the highest achieved membership, make note...*/ int k; - for ( k=0; k<1; k++ ) { + for ( k=0; k max_max_members) { max_max_members = max_members; - best_i = i; - best_j = j; - best_i_idx = i_idx[k]; - best_j_idx = j_idx[k]; + gsl_matrix_free(best_rotation); + best_rotation = *rotation; + } else { + gsl_matrix_free(*rotation); + *rotation = NULL; } } + + unsigned long now_time = time(NULL); + unsigned int seconds = now_time - start_time; + + if (seconds > 60) { + /* Heading towards CrystFEL cutoff so + return your best guess and run */ + *rotation = best_rotation; + STATUS("After %i seconds, returning best guess\n", seconds); + return (best_rotation != NULL); + } } } } /* yes this } is meant to be here */ - int max_members = 0; - int success = start_seed(obs_vecs, obs_vec_count, best_i, best_j, - best_i_idx, best_j_idx, - rotation, &max_members, - 1); - - if (success) { - return success; - } else { - /* Well, shit... something went wrong. */ - return 0; - } + *rotation = best_rotation; + return (best_rotation != NULL); } @@ -1017,8 +1090,11 @@ global_nrlps = rlp_count; cleanup_taketwo_cell_vecs(cell_vecs); - find_seed(obs_vecs, obs_vec_count, &solution); - if ( solution == NULL ) return NULL; + int threshold_reached = find_seed(obs_vecs, obs_vec_count, &solution); + + if ( solution == NULL ) { + return NULL; + } result = transform_cell_gsl(cell, solution); @@ -1052,6 +1128,8 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) rlps[n_rlps].v = 0.0; rlps[n_rlps++].w = 0.0; +// STATUS("n_rlps = %i", n_rlps); + cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; @@ -1099,6 +1177,11 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, ERROR("TakeTwo indexing requires a unit cell.\n"); return NULL; } + + STATUS("Welcome to TakeTwo\n"); + STATUS("If you use these indexing results, please cite:\n"); + STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); + tp = malloc(sizeof(struct taketwo_private)); if ( tp == NULL ) return NULL; -- cgit v1.2.3 From 9ea9540f63308769c9f035ed5108b93c680520ed Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 13:39:40 +0000 Subject: Goodbye memory leaks! --- libcrystfel/src/taketwo.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 7e545fd2..6e58bb46 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -391,6 +391,9 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); gsl_matrix_transpose(fullMat); + + free(cell2v); + free(cell2vr); return fullMat; } @@ -509,8 +512,6 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, /* placeholders, but results are ignored */ int match_count = 0; - int *her_match_idxs; - int *his_match_idxs; /* check our test vector matches existing network member */ int success = obs_vecs_match_angles(her_obs, his_obs, @@ -656,9 +657,15 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if (all_ok) { *match_found = test_idx[j]; + free(member_idx); + free(test_idx); return i; } } + + free(member_idx); member_idx = NULL; + free(test_idx); member_idx = NULL; + } /* give up. */ @@ -844,12 +851,16 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, if (seconds > 60) { /* Heading towards CrystFEL cutoff so return your best guess and run */ + + free(i_idx); free(j_idx); *rotation = best_rotation; STATUS("After %i seconds, returning best guess\n", seconds); return (best_rotation != NULL); } } + free(i_idx); i_idx = NULL; + free(j_idx); j_idx = NULL; } } /* yes this } is meant to be here */ -- cgit v1.2.3 From a4ead6e4882edb76baea2fab7a4e4a6d25e04db0 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 14:50:14 +0000 Subject: Fixed more memory errors --- libcrystfel/src/taketwo.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 6e58bb46..4655868c 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -71,15 +71,12 @@ struct taketwo_private UnitCell *cell; }; -struct rvec *global_rlps; -int global_nrlps; - /* Maximum distance between two rlp sizes to consider info for indexing */ #define MAX_RECIP_DISTANCE (0.12*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.0005*1e10) +#define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ #define NETWORK_MEMBER_THRESHOLD (20) @@ -317,6 +314,7 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, if (score != NULL) *score = tr; gsl_matrix_free(mul); + gsl_matrix_free(sub); double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); return (tr < max); @@ -394,6 +392,8 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, free(cell2v); free(cell2vr); + free(secondTwizzleMatrix); + free(rotateSpotDiffMatrix); return fullMat; } @@ -646,13 +646,13 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, double trace = 0; int ok = rot_mats_are_similar(rot, test_rot, &trace); + free(test_rot); if (!ok) { all_ok = 0; break; } - free(test_rot); } if (all_ok) { @@ -756,15 +756,6 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } -static signed int spot_idx(struct rvec *rlp) -{ - int i; - for ( i=0; i max_max_members) { max_max_members = max_members; @@ -848,13 +840,12 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, unsigned long now_time = time(NULL); unsigned int seconds = now_time - start_time; - if (seconds > 60) { + if (seconds > 30) { /* Heading towards CrystFEL cutoff so return your best guess and run */ free(i_idx); free(j_idx); *rotation = best_rotation; - STATUS("After %i seconds, returning best guess\n", seconds); return (best_rotation != NULL); } } @@ -1088,9 +1079,6 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) success = gen_theoretical_vecs(cell, &cell_vecs, &cell_vec_count); if ( !success ) return NULL; -global_rlps = rlps; -global_nrlps = rlp_count; - success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count); if ( !success ) return NULL; @@ -1139,11 +1127,11 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) rlps[n_rlps].v = 0.0; rlps[n_rlps++].w = 0.0; -// STATUS("n_rlps = %i", n_rlps); - cell = run_taketwo(tp->cell, rlps, n_rlps); if ( cell == NULL ) return 0; + free(rlps); + cr = crystal_new(); if ( cr == NULL ) { ERROR("Failed to allocate crystal.\n"); @@ -1156,6 +1144,7 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) if ( !peak_sanity_check(image, &cr, 1) ) { cell_free(cell); crystal_free(cr); + return 0; } } -- cgit v1.2.3 From d0e91daf966ac3338b01e2f139910140d9417a1d Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 15:25:25 +0000 Subject: Significant reduction in leakage, not done yet. --- libcrystfel/src/taketwo.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 4655868c..129cdb4b 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -390,10 +390,10 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); gsl_matrix_transpose(fullMat); - free(cell2v); - free(cell2vr); - free(secondTwizzleMatrix); - free(rotateSpotDiffMatrix); + gsl_vector_free(cell2v); + gsl_vector_free(cell2vr); + gsl_matrix_free(secondTwizzleMatrix); + gsl_matrix_free(rotateSpotDiffMatrix); return fullMat; } @@ -628,7 +628,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int all_ok = 1; for ( k=0; kcell, rlps, n_rlps); - if ( cell == NULL ) return 0; - free(rlps); + if ( cell == NULL ) return 0; cr = crystal_new(); if ( cr == NULL ) { -- cgit v1.2.3 From 160ff6d0204f050147bc855977ff7c19c71a5acb Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 16:01:25 +0000 Subject: One image has no more leaks from taketwo.c --- libcrystfel/src/taketwo.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 129cdb4b..4b74adbb 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -536,6 +536,7 @@ static signed int finalise_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); int i, j, count; + for ( i=0; i<1; i++ ) { for ( j=0; j max_max_members) { max_max_members = max_members; gsl_matrix_free(best_rotation); best_rotation = *rotation; + *rotation = NULL; } else { gsl_matrix_free(*rotation); *rotation = NULL; @@ -843,18 +851,20 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, if (seconds > 30) { /* Heading towards CrystFEL cutoff so return your best guess and run */ - free(i_idx); free(j_idx); + *rotation = best_rotation; - return (best_rotation != NULL); + STATUS("Return timeout\n"); + return (best_rotation != NULL); } } - free(i_idx); i_idx = NULL; - free(j_idx); j_idx = NULL; + free(i_idx); + free(j_idx); } } /* yes this } is meant to be here */ + STATUS("Return exhaustion\n"); *rotation = best_rotation; return (best_rotation != NULL); } @@ -1097,7 +1107,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) } result = transform_cell_gsl(cell, solution); - + gsl_matrix_free(solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); return result; -- cgit v1.2.3 From 2cefd4a8807d87cbe459c83d4b944d32ee38d2af Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 18 Jan 2017 16:01:52 +0000 Subject: Remove error messages --- libcrystfel/src/taketwo.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 4b74adbb..b92743b4 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -831,7 +831,6 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, if (success) { free(i_idx); free(j_idx); gsl_matrix_free(best_rotation); - STATUS("Return normal\n"); return success; } else { if (max_members > max_max_members) { @@ -854,8 +853,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, free(i_idx); free(j_idx); *rotation = best_rotation; - STATUS("Return timeout\n"); - return (best_rotation != NULL); + return (best_rotation != NULL); } } @@ -864,8 +862,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, } } /* yes this } is meant to be here */ - STATUS("Return exhaustion\n"); - *rotation = best_rotation; + *rotation = best_rotation; return (best_rotation != NULL); } -- cgit v1.2.3 From 86090bb75eaa406d9e99dc03687ed937b8a84485 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Fri, 24 Mar 2017 15:19:55 +0000 Subject: Now tries the shortest vectors first. --- libcrystfel/src/taketwo.c | 815 ++++++++++++++++++++++++---------------------- 1 file changed, 417 insertions(+), 398 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b92743b4..a1e51c2a 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -73,7 +73,7 @@ struct taketwo_private /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.12*1e10) +#define MAX_RECIP_DISTANCE (0.20*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ #define RECIP_TOLERANCE (0.001*1e10) @@ -88,7 +88,7 @@ struct taketwo_private #define MAX_DEAD_ENDS (5) /* Tolerance for two angles to be considered the same */ -#define ANGLE_TOLERANCE (deg2rad(1.0)) +#define ANGLE_TOLERANCE (deg2rad(3.0)) /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(3.0)) @@ -129,8 +129,8 @@ static struct rvec new_rvec(double new_u, double new_v, double new_w) static struct rvec diff_vec(struct rvec from, struct rvec to) { struct rvec diff = new_rvec(to.u - from.u, - to.v - from.v, - to.w - from.w); + to.v - from.v, + to.w - from.w); return diff; } @@ -151,10 +151,10 @@ static double rvec_length(struct rvec vec) static void normalise_rvec(struct rvec *vec) { - double length = rvec_length(*vec); - vec->u /= length; - vec->v /= length; - vec->w /= length; + double length = rvec_length(*vec); + vec->u /= length; + vec->v /= length; + vec->w /= length; } @@ -193,8 +193,8 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) static void show_rvec(struct rvec r2) { - struct rvec r = r2; - normalise_rvec(&r); + struct rvec r = r2; + normalise_rvec(&r); STATUS("[ %.3f %.3f %.3f ]\n", r.u, r.v, r.w); } @@ -229,7 +229,7 @@ static gsl_matrix *rotation_around_axis(struct rvec c, double th) * that @result has already been allocated. Will upload the maths to the * shared Google drive. */ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, - struct rvec axis) + struct rvec axis) { /* Let's have unit vectors */ normalise_rvec(&vec1); @@ -244,8 +244,8 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, /* Components in handwritten maths online when I upload it */ double A = a*(p*x*x - p + x*y*q + x*z*r) + - b*(p*x*y + q*y*y - q + r*y*z) + - c*(p*x*z + q*y*z + r*z*z - r); + b*(p*x*y + q*y*y - q + r*y*z) + + c*(p*x*z + q*y*z + r*z*z - r); double B = a*(y*r - z*q) + b*(p*z - r*x) + c*(q*x - p*y); @@ -256,26 +256,26 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, * and we need to work out which one. This could potentially be * simplified - do we really need so many cos/sins? maybe check * the 2nd derivative instead? */ - double cc = cos(theta); - double C = 1 - cc; - double s = sin(theta); - double occ = -cc; - double oC = 1 - occ; - double os = -s; + double cc = cos(theta); + double C = 1 - cc; + double s = sin(theta); + double occ = -cc; + double oC = 1 - occ; + double os = -s; - double pPrime = (x*x*C+cc)*p + (x*y*C-z*s)*q + (x*z*C+y*s)*r; - double qPrime = (y*x*C+z*s)*p + (y*y*C+cc)*q + (y*z*C-x*s)*r; - double rPrime = (z*x*C-y*s)*p + (z*y*C+x*s)*q + (z*z*C+cc)*r; + double pPrime = (x*x*C+cc)*p + (x*y*C-z*s)*q + (x*z*C+y*s)*r; + double qPrime = (y*x*C+z*s)*p + (y*y*C+cc)*q + (y*z*C-x*s)*r; + double rPrime = (z*x*C-y*s)*p + (z*y*C+x*s)*q + (z*z*C+cc)*r; - double pDbPrime = (x*x*oC+occ)*p + (x*y*oC-z*os)*q + (x*z*oC+y*os)*r; - double qDbPrime = (y*x*oC+z*os)*p + (y*y*oC+occ)*q + (y*z*oC-x*os)*r; - double rDbPrime = (z*x*oC-y*os)*p + (z*y*oC+x*os)*q + (z*z*oC+occ)*r; + double pDbPrime = (x*x*oC+occ)*p + (x*y*oC-z*os)*q + (x*z*oC+y*os)*r; + double qDbPrime = (y*x*oC+z*os)*p + (y*y*oC+occ)*q + (y*z*oC-x*os)*r; + double rDbPrime = (z*x*oC-y*os)*p + (z*y*oC+x*os)*q + (z*z*oC+occ)*r; - double cosAlpha = pPrime * a + qPrime * b + rPrime * c; - double cosAlphaOther = pDbPrime * a + qDbPrime * b + rDbPrime * c; + double cosAlpha = pPrime * a + qPrime * b + rPrime * c; + double cosAlphaOther = pDbPrime * a + qDbPrime * b + rDbPrime * c; - int addPi = (cosAlphaOther > cosAlpha); - double bestAngle = theta + addPi * M_PI; + int addPi = (cosAlphaOther > cosAlpha); + double bestAngle = theta + addPi * M_PI; /* Return an identity matrix which has been rotated by * theta around "axis" */ @@ -297,7 +297,7 @@ static double matrix_trace(gsl_matrix *a) static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, - double *score) + double *score) { double tr; gsl_matrix *sub; @@ -312,12 +312,12 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, tr = matrix_trace(mul); if (score != NULL) *score = tr; - + gsl_matrix_free(mul); gsl_matrix_free(sub); - double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); + double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); - return (tr < max); + return (tr < max); } @@ -355,7 +355,7 @@ struct rvec gsl_to_rvec(gsl_vector *a) * intensive on the number crunching side so simple angle checks are used * to 'pre-scan' vectors beforehand. */ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, - struct rvec cell1, struct rvec cell2) + struct rvec cell1, struct rvec cell2) { gsl_matrix *rotateSpotDiffMatrix; gsl_matrix *secondTwizzleMatrix; @@ -363,33 +363,33 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, gsl_vector *cell2v = rvec_to_gsl(cell2); gsl_vector *cell2vr = gsl_vector_calloc(3); - normalise_rvec(&obs1); - normalise_rvec(&obs2); - normalise_rvec(&cell1); - normalise_rvec(&cell2); + normalise_rvec(&obs1); + normalise_rvec(&obs2); + normalise_rvec(&cell1); + normalise_rvec(&cell2); - /* Rotate reciprocal space so that the first simulated vector lines up - * with the observed vector. */ - rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); + /* Rotate reciprocal space so that the first simulated vector lines up + * with the observed vector. */ + rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); - normalise_rvec(&obs1); + normalise_rvec(&obs1); - /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, - 0.0, cell2vr); + /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ + gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, + 0.0, cell2vr); - /* Now we twirl around the firstAxisUnit until the rotated simulated - * vector matches the second observed vector as closely as possible. */ + /* Now we twirl around the firstAxisUnit until the rotated simulated + * vector matches the second observed vector as closely as possible. */ - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); + secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ fullMat = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, - rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); + rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); gsl_matrix_transpose(fullMat); - + gsl_vector_free(cell2v); gsl_vector_free(cell2vr); gsl_matrix_free(secondTwizzleMatrix); @@ -403,9 +403,9 @@ static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) { /* FIXME: Disgusting... can I tone this down a bit? */ if ( (her_obs->her_rlp == his_obs->her_rlp) || - (her_obs->her_rlp == his_obs->his_rlp) || - (her_obs->his_rlp == his_obs->her_rlp) || - (her_obs->his_rlp == his_obs->his_rlp) ) { + (her_obs->her_rlp == his_obs->his_rlp) || + (her_obs->his_rlp == his_obs->her_rlp) || + (her_obs->his_rlp == his_obs->his_rlp) ) { return 1; } @@ -414,7 +414,7 @@ static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, - int *members, int num) + int *members, int num) { int i; struct SpotVec *her_obs = &obs_vecs[test_idx]; @@ -437,15 +437,15 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, * cosine graph are more sensitive than others, so may be a trade off... or not. */ static int obs_vecs_match_angles(struct SpotVec *her_obs, - struct SpotVec *his_obs, + struct SpotVec *his_obs, int **her_match_idxs, int **his_match_idxs, int *match_count) { - int i, j; + int i, j; *match_count = 0; - // *her_match_idx = -1; - // *his_match_idx = -1; + // *her_match_idx = -1; + // *his_match_idx = -1; /* calculate angle between observed vectors */ double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); @@ -453,42 +453,43 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, /* calculate angle between all potential theoretical vectors */ for ( i=0; imatch_num; i++ ) { - for ( j=0; jmatch_num; j++ ) { + for ( j=0; jmatch_num; j++ ) { - struct rvec *her_match = &her_obs->matches[i]; - struct rvec *his_match = &his_obs->matches[j]; + struct rvec *her_match = &her_obs->matches[i]; + struct rvec *his_match = &his_obs->matches[j]; - double theory_angle = rvec_angle(*her_match, *his_match); + double theory_angle = rvec_angle(*her_match, + *his_match); - /* is this angle a match? */ + /* is this angle a match? */ - double angle_diff = fabs(theory_angle - obs_angle); + double angle_diff = fabs(theory_angle - obs_angle); - if ( angle_diff < ANGLE_TOLERANCE ) { - size_t new_size = (*match_count + 1) * - sizeof(int); - if (her_match_idxs && his_match_idxs) - { - /* Reallocate the array to fit in another match */ - int *temp_hers; - temp_hers = realloc(*her_match_idxs, new_size); - int *temp_his; - temp_his = realloc(*his_match_idxs, new_size); + if ( angle_diff < ANGLE_TOLERANCE ) { + size_t new_size = (*match_count + 1) * + sizeof(int); + if (her_match_idxs && his_match_idxs) + { + /* Reallocate the array to fit in another match */ + int *temp_hers; + temp_hers = realloc(*her_match_idxs, new_size); + int *temp_his; + temp_his = realloc(*his_match_idxs, new_size); - if ( temp_hers == NULL || temp_his == NULL ) { - apologise(); - } + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); + } - (*her_match_idxs) = temp_hers; - (*his_match_idxs) = temp_his; + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; - (*her_match_idxs)[*match_count] = i; - (*his_match_idxs)[*match_count] = j; - } + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; + } - (*match_count)++; - } - } + (*match_count)++; + } + } } return (*match_count > 0); @@ -496,7 +497,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, - int *obs_members, int *match_members, int num) + int *obs_members, int *match_members, int num) { /* note: this is just a preliminary check to reduce unnecessary * computation later down the line, but is not entirely accurate. @@ -511,13 +512,13 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, struct SpotVec *his_obs = &obs_vecs[obs_members[i]]; /* placeholders, but results are ignored */ - int match_count = 0; + int match_count = 0; /* check our test vector matches existing network member */ int success = obs_vecs_match_angles(her_obs, his_obs, - NULL, NULL, - &match_count); - + NULL, NULL, + &match_count); + if (!success) return 0; } @@ -530,82 +531,82 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, * ------------------------------------------------------------------------*/ static signed int finalise_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, - int *obs_members, int *match_members, - int member_num) + int *obs_members, int *match_members, + int member_num) { - gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); - - int i, j, count; - - for ( i=0; i<1; i++ ) { - for ( j=0; j obs_vec_count) { - return 0; - } - - int match_found = -1; - - signed int next_index = find_next_index(rot, obs_vecs, - obs_vec_count, obs_members, - match_members, - start, member_num, - &match_found, 0); - - if ( member_num < 2 ) { - return 0; - } - - if ( next_index < 0 ) { - /* If there have been too many dead ends, give up - * on indexing altogether. - **/ - if ( dead_ends > MAX_DEAD_ENDS ) { - break; - } - - /* We have not had too many dead ends. Try removing - the last member and continue. */ - start++; - member_num--; - dead_ends++; - - continue; - } - - /* we have elongated membership - so reset dead_ends counter */ - dead_ends = 0; - - obs_members[member_num] = next_index; - match_members[member_num] = match_found; - - start = next_index + 1; - member_num++; - - if (member_num > *max_members) { - *max_members = member_num; - } - - /* If member_num is high enough, we want to return a yes */ - if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; + if (start > obs_vec_count) { + return 0; + } + + int match_found = -1; + + signed int next_index = find_next_index(rot, obs_vecs, + obs_vec_count, obs_members, + match_members, + start, member_num, + &match_found, 0); + + if ( member_num < 2 ) { + return 0; + } + + if ( next_index < 0 ) { + /* If there have been too many dead ends, give up + * on indexing altogether. + **/ + if ( dead_ends > MAX_DEAD_ENDS ) { + break; + } + + /* We have not had too many dead ends. Try removing + the last member and continue. */ + start++; + member_num--; + dead_ends++; + + continue; + } + + /* we have elongated membership - so reset dead_ends counter */ + dead_ends = 0; + + obs_members[member_num] = next_index; + match_members[member_num] = match_found; + + start = next_index + 1; + member_num++; + + if (member_num > *max_members) { + *max_members = member_num; + } + + /* If member_num is high enough, we want to return a yes */ + if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } - finalise_solution(rot, obs_vecs, obs_members, - match_members, member_num); + finalise_solution(rot, obs_vecs, obs_members, + match_members, member_num); return ( member_num > NETWORK_MEMBER_THRESHOLD ); } static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, - int j, int i_match, int j_match, gsl_matrix **rotation, - int *max_members) + int j, int i_match, int j_match, gsl_matrix **rotation, + int *max_members) { - gsl_matrix *rot_mat; - - rot_mat = generate_rot_mat(obs_vecs[i].obsvec, - obs_vecs[j].obsvec, - obs_vecs[i].matches[i_match], - obs_vecs[j].matches[j_match]); - - /* Try to expand this rotation matrix to a larger network */ - - int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_match, j_match, max_members); - - /* return this matrix and if it was immediately successful */ - *rotation = rot_mat; - - return success; + gsl_matrix *rot_mat; + + rot_mat = generate_rot_mat(obs_vecs[i].obsvec, + obs_vecs[j].obsvec, + obs_vecs[i].matches[i_match], + obs_vecs[j].matches[j_match]); + + /* Try to expand this rotation matrix to a larger network */ + + int success = grow_network(rot_mat, obs_vecs, obs_vec_count, + i, j, i_match, j_match, max_members); + + /* return this matrix and if it was immediately successful */ + *rotation = rot_mat; + + return success; } static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, - gsl_matrix **rotation) + gsl_matrix **rotation) { - /* META: Maximum achieved maximum network membership */ + /* META: Maximum achieved maximum network membership */ int max_max_members = 0; gsl_matrix *best_rotation = NULL; - + unsigned long start_time = time(NULL); - + /* loop round pairs of vectors to try and find a suitable * seed to start building a self-consistent network of vectors */ int i, j; - - for ( i=0; i max_max_members) { - max_max_members = max_members; - gsl_matrix_free(best_rotation); - best_rotation = *rotation; - *rotation = NULL; - } else { - gsl_matrix_free(*rotation); - *rotation = NULL; - } - } - - unsigned long now_time = time(NULL); - unsigned int seconds = now_time - start_time; - - if (seconds > 30) { - /* Heading towards CrystFEL cutoff so - return your best guess and run */ - free(i_idx); free(j_idx); - - *rotation = best_rotation; - return (best_rotation != NULL); - } + for ( i=0; i max_max_members) { + max_max_members = max_members; + gsl_matrix_free(best_rotation); + best_rotation = *rotation; + *rotation = NULL; + } else { + gsl_matrix_free(*rotation); + *rotation = NULL; + } + } + + unsigned long now_time = time(NULL); + unsigned int seconds = now_time - start_time; + + // Commented out for the time being. + /* + if (seconds > 30) { + // Heading towards CrystFEL cutoff so + // return your best guess and run + free(i_idx); free(j_idx); + + *rotation = best_rotation; + return (best_rotation != NULL); + } + */ + } + + free(i_idx); + free(j_idx); } - - free(i_idx); - free(j_idx); - } } /* yes this } is meant to be here */ *rotation = best_rotation; @@ -882,7 +887,7 @@ static int sort_func(const void *av, const void *bv) static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, - struct SpotVec *obs_vecs, int obs_vec_count) + struct SpotVec *obs_vecs, int obs_vec_count) { int i, j; @@ -912,8 +917,10 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, for_sort[count].v = cell_vecs[j]; for_sort[count].dist = dist_diff; count++; - + } + + /* Sort in order to get most agreeable matches first */ qsort(for_sort, count, sizeof(struct sortme), sort_func); obs_vecs[i].matches = malloc(count*sizeof(struct rvec)); obs_vecs[i].match_num = count; @@ -927,9 +934,15 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, return 1; } +static int compare_spot_vecs(const void *av, const void *bv) +{ + struct SpotVec *a = (struct SpotVec *)av; + struct SpotVec *b = (struct SpotVec *)bv; + return a->distance > b->distance; +} static int gen_observed_vecs(struct rvec *rlps, int rlp_count, - struct SpotVec **obs_vecs, int *obs_vec_count) + struct SpotVec **obs_vecs, int *obs_vec_count) { int i, j; int count = 0; @@ -940,7 +953,7 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, for ( i=0; i max_sq_length ) continue; - + count++; struct SpotVec *temp_obs_vecs; temp_obs_vecs = realloc(*obs_vecs, - count*sizeof(struct SpotVec)); + count*sizeof(struct SpotVec)); if ( temp_obs_vecs == NULL ) { return 0; @@ -975,6 +988,11 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, } } + /* Sort such that the shortest and least error-prone distances + are searched first. + */ + qsort(*obs_vecs, count, sizeof(struct SpotVec), compare_spot_vecs); + *obs_vec_count = count; return 1; @@ -982,7 +1000,7 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, - int *vec_count) + int *vec_count) { double a, b, c, alpha, beta, gamma; int h_max, k_max, l_max; @@ -1001,37 +1019,37 @@ static int gen_theoretical_vecs(UnitCell *cell, struct rvec **cell_vecs, int count = 0; cell_get_reciprocal(cell, &asx, &asy, &asz, - &bsx, &bsy, &bsz, - &csx, &csy, &csz); + &bsx, &bsy, &bsz, + &csx, &csy, &csz); for ( h=-h_max; h<=+h_max; h++ ) { - for ( k=-k_max; k<=+k_max; k++ ) { - for ( l=-l_max; l<=+l_max; l++ ) { + for ( k=-k_max; k<=+k_max; k++ ) { + for ( l=-l_max; l<=+l_max; l++ ) { - struct rvec cell_vec; + struct rvec cell_vec; - /* Exclude systematic absences from centering concerns */ - if ( forbidden_reflection(cell, h, k, l) ) continue; + /* Exclude systematic absences from centering concerns */ + if ( forbidden_reflection(cell, h, k, l) ) continue; - cell_vec.u = h*asx + k*bsx + l*csx; - cell_vec.v = h*asy + k*bsy + l*csy; - cell_vec.w = h*asz + k*bsz + l*csz; + cell_vec.u = h*asx + k*bsx + l*csx; + cell_vec.v = h*asy + k*bsy + l*csy; + cell_vec.w = h*asz + k*bsz + l*csz; - /* add this to our array - which may require expanding */ - count++; + /* add this to our array - which may require expanding */ + count++; - struct rvec *temp_cell_vecs; - temp_cell_vecs = realloc(*cell_vecs, count*sizeof(struct rvec)); + struct rvec *temp_cell_vecs; + temp_cell_vecs = realloc(*cell_vecs, count*sizeof(struct rvec)); - if ( temp_cell_vecs == NULL ) { - return 0; - } else { - *cell_vecs = temp_cell_vecs; - (*cell_vecs)[count - 1] = cell_vec; + if ( temp_cell_vecs == NULL ) { + return 0; + } else { + *cell_vecs = temp_cell_vecs; + (*cell_vecs)[count - 1] = cell_vec; + } + } } } - } - } *vec_count = count; @@ -1050,7 +1068,7 @@ static void cleanup_taketwo_cell_vecs(struct rvec *cell_vecs) static void cleanup_taketwo_obs_vecs(struct SpotVec *obs_vecs, - int obs_vec_count) + int obs_vec_count) { int i; for ( i=0; ifeatures)+1)*sizeof(struct rvec)); - for ( i=0; ifeatures); i++ ) { - struct imagefeature *pk = image_get_feature(image->features, i); - if ( pk == NULL ) continue; - rlps[n_rlps].u = pk->rx; - rlps[n_rlps].v = pk->ry; - rlps[n_rlps].w = pk->rz; - n_rlps++; - } - rlps[n_rlps].u = 0.0; - rlps[n_rlps].v = 0.0; - rlps[n_rlps++].w = 0.0; + rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); + for ( i=0; ifeatures); i++ ) { + struct imagefeature *pk = image_get_feature(image->features, i); + if ( pk == NULL ) continue; + rlps[n_rlps].u = pk->rx; + rlps[n_rlps].v = pk->ry; + rlps[n_rlps].w = pk->rz; + n_rlps++; + } + rlps[n_rlps].u = 0.0; + rlps[n_rlps].v = 0.0; + rlps[n_rlps++].w = 0.0; cell = run_taketwo(tp->cell, rlps, n_rlps); - free(rlps); + free(rlps); if ( cell == NULL ) return 0; cr = crystal_new(); @@ -1151,7 +1169,7 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) if ( !peak_sanity_check(image, &cr, 1) ) { cell_free(cell); crystal_free(cr); - + return 0; } } @@ -1163,17 +1181,17 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, - struct detector *det, float *ltl) + struct detector *det, float *ltl) { struct taketwo_private *tp; /* Flags that TakeTwo knows about */ *indm &= INDEXING_METHOD_MASK | INDEXING_CHECK_PEAKS - | INDEXING_USE_LATTICE_TYPE | INDEXING_USE_CELL_PARAMETERS - | INDEXING_CONTROL_FLAGS; + | INDEXING_USE_LATTICE_TYPE | INDEXING_USE_CELL_PARAMETERS + | INDEXING_CONTROL_FLAGS; if ( !( (*indm & INDEXING_USE_LATTICE_TYPE) - && (*indm & INDEXING_USE_CELL_PARAMETERS)) ) + && (*indm & INDEXING_USE_CELL_PARAMETERS)) ) { ERROR("TakeTwo indexing requires cell and lattice type " "information.\n"); @@ -1184,19 +1202,19 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, ERROR("TakeTwo indexing requires a unit cell.\n"); return NULL; } - - STATUS("Welcome to TakeTwo\n"); - STATUS("If you use these indexing results, please cite:\n"); - STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); - + STATUS("Welcome to TakeTwo\n"); + STATUS("If you use these indexing results, please cite:\n"); + STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); + + tp = malloc(sizeof(struct taketwo_private)); if ( tp == NULL ) return NULL; - + tp->ltl = ltl; tp->cell = cell; tp->indm = *indm; - + return (IndexingPrivate *)tp; } @@ -1206,3 +1224,4 @@ void taketwo_cleanup(IndexingPrivate *pp) struct taketwo_private *tp = (struct taketwo_private *)pp; free(tp); } + -- cgit v1.2.3 From dff98b66ddf64cbe0f54fa542cc9a704a122e041 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Thu, 18 May 2017 13:07:10 +0100 Subject: Various fiddles to add symmetry operations but not functional --- libcrystfel/src/taketwo.c | 164 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index a1e51c2a..525652a9 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1,3 +1,15 @@ +// +// ignore.h +// cppxfel +// +// Created by Helen Ginn on 24/03/2017. +// Copyright (c) 2017 Division of Structural Biology Oxford. All rights reserved. +// + +#ifndef cppxfel_ignore_h +#define cppxfel_ignore_h + + /* * taketwo.c * @@ -38,6 +50,7 @@ #include "index.h" #include "taketwo.h" #include "peaks.h" +#include "symmetry.h" #include /** @@ -71,6 +84,14 @@ struct taketwo_private UnitCell *cell; }; +// These rotation symmetry operators +struct TakeTwoCell +{ + UnitCell *cell; + gsl_matrix **rotSymOps; + unsigned int numOps; +}; + /* Maximum distance between two rlp sizes to consider info for indexing */ #define MAX_RECIP_DISTANCE (0.20*1e10) @@ -295,6 +316,11 @@ static double matrix_trace(gsl_matrix *a) return tr; } +static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, + struct TakeTwoCell *cell) +{ + +} static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, double *score) @@ -431,7 +457,6 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, } -// FIXME: decide if match count is returned or put in variable name /** Note: this could potentially (and cautiously) converted to comparing * cosines rather than angles, to lose an "acos" but different parts of the * cosine graph are more sensitive than others, so may be a trade off... or not. @@ -781,8 +806,55 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, return success; } +static int weed_duplicate_matches(struct SpotVec *her_obs, + struct SpotVec *his_obs, + int **her_match_idxs, int **his_match_idxs, + int *match_count, struct TakeTwoCell *cell) +{ + gsl_matrix **old_mats = calloc(sizeof(gsl_matrix *) * match_count); + int num_occupied = 0; + + + signed int i, j; + for (i = match_count - 1; i >= 0; i++) { + int her_match = (*her_match_idxs)[i]; + int his_match = (*his_match_idxs)[i]; + + struct rvec i_obsvec = her_obs->obsvec; + struct rvec j_obsvec = his_obs->obsvec; + struct rvec i_cellvec = her_obs->matches[her_match]; + struct rvec j_cellvec = his_obs->matches[his_match]; + + gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, + i_cellvec, j_cellvec); + + for (j = 0; j < num_occupied; j++) { + if (old_mats[j] && + symm_rot_mats_are_similar(old_mats[j], mat, cell)) { + // we have found a duplicate, so flag as bad. + (*her_match_idxs)[i] = -1; + (*his_match_idxs)[i] = -1; + + gsl_matrix_free(mat); + } else { + // we have not found a duplicate, add to list. + old_mats[num_occupied] = mat; + num_occupied++; + } + } + } + + for (i = 0; i < num_occupied; i++) { + if (old_mats[i]) { + gsl_matrix_free(old_mats[i]); + } + } + + free(old_mats); +} + static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, - gsl_matrix **rotation) + gsl_matrix **rotation, struct TakeTwoCell *cell) { /* META: Maximum achieved maximum network membership */ int max_max_members = 0; @@ -806,7 +878,9 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, if ( !shared ) continue; - /* cell vector "matches" index for i, j respectively */ + /* cell vector index matches stored in i, j and total number + * stored in int matches. + */ int *i_idx = 0; int *j_idx = 0; int matches; @@ -820,10 +894,21 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, continue; } + /* Weed out the duplicate seeds (from symmetric + * reflection pairs) + */ + + weed_duplicate_matches(&obs_vecs[i], &obs_vecs[j], + &i_idx, &j_idx, &matches, cell); + /* We have seeds! Pass each of them through the seed-starter */ /* If a seed has the highest achieved membership, make note...*/ int k; for ( k=0; kcell); + SymOpList rawList; + + switch (lattice) { + case L_TRICLINIC: + // ...get parental guidance for unusually accurate candidness? + rawList = getpg_uac("1"); + break; + case L_MONOCLINIC: + rawList = getpg_uac("2"); + break; + case L_ORTHORHOMBIC: + rawList = getpg_uac("222"); + break; + case L_TETRAGONAL: + rawList = getpg_uac("422"); + break; + case L_RHOMBOHEDRAL: + rawList = getpg_uac("312_H"); // uhmmm, sure? + break; + case L_HEXAGONAL: + rawList = getpg_uac("622"); + break; + case L_CUBIC: + rawList = getpg_uac("432"); + break; + default: + break; + } + + /* Now we must convert these into rotation matrices rather than hkl + * transformations (affects triclinic, monoclinic, rhombohedral and + * hexagonal space groups only) */ + + cell_get_reciprocal(ttCell->cell, &asx, &asy, &asz, &bsx, &bsy, + &bsz, &csx, &csy, &csz); + + inv = gsl_matrix_alloc(3, 3); + gsl_matrix_set(inv, 0, 0, asx); + gsl_matrix_set(inv, 0, 1, asy); + gsl_matrix_set(inv, 0, 2, asz); + gsl_matrix_set(inv, 1, 0, bsx); + gsl_matrix_set(inv, 1, 1, bsy); + gsl_matrix_set(inv, 1, 2, bsz); + gsl_matrix_set(inv, 2, 0, csx); + gsl_matrix_set(inv, 2, 1, csy); + gsl_matrix_set(inv, 2, 2, csz); + + // FIXME: Finish me! Along the lines of: + /* + MatrixPtr newMat = matFromCCP4(&spaceGroup->symop[j]); + MatrixPtr ortho = newMat; + ortho->preMultiply(*unitCell); + ortho->multiply(*reverse); + */ + + gsl_matrix_free(inv); +} + struct sortme { @@ -1114,7 +1260,15 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) if ( !success ) return NULL; - int threshold_reached = find_seed(obs_vecs, obs_vec_count, &solution); + struct TakeTwoCell ttCell; + ttCell.cell = cell; + ttCell.rotSymOps = NULL; + ttCell.numOps = 0; + + int success = generate_rotation_sym_ops(&ttCell); + + int threshold_reached = find_seed(obs_vecs, obs_vec_count, + &solution, cell); if ( solution == NULL ) { cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); @@ -1225,3 +1379,5 @@ void taketwo_cleanup(IndexingPrivate *pp) free(tp); } + +#endif -- cgit v1.2.3 From 67d16a69113a81555a14c90c2b69d2b4cf2cb831 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 18 May 2017 14:16:36 +0200 Subject: Fix uninitialised variable --- libcrystfel/src/taketwo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 525652a9..0ea4c499 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -563,6 +563,7 @@ static signed int finalise_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, int i, j, count; + count = 0; for ( i=0; i<1; i++ ) { for ( j=0; j Date: Thu, 18 May 2017 14:17:19 +0200 Subject: Formatting --- libcrystfel/src/taketwo.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 0ea4c499..08b78af4 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -317,7 +317,7 @@ static double matrix_trace(gsl_matrix *a) } static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, - struct TakeTwoCell *cell) + struct TakeTwoCell *cell) { } @@ -808,13 +808,12 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, } static int weed_duplicate_matches(struct SpotVec *her_obs, - struct SpotVec *his_obs, - int **her_match_idxs, int **his_match_idxs, - int *match_count, struct TakeTwoCell *cell) + struct SpotVec *his_obs, + int **her_match_idxs, int **his_match_idxs, + int *match_count, struct TakeTwoCell *cell) { gsl_matrix **old_mats = calloc(sizeof(gsl_matrix *) * match_count); int num_occupied = 0; - signed int i, j; for (i = match_count - 1; i >= 0; i++) { @@ -827,11 +826,12 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, struct rvec j_cellvec = his_obs->matches[his_match]; gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, - i_cellvec, j_cellvec); + i_cellvec, j_cellvec); for (j = 0; j < num_occupied; j++) { if (old_mats[j] && - symm_rot_mats_are_similar(old_mats[j], mat, cell)) { + symm_rot_mats_are_similar(old_mats[j], mat, cell)) + { // we have found a duplicate, so flag as bad. (*her_match_idxs)[i] = -1; (*his_match_idxs)[i] = -1; @@ -1361,15 +1361,14 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, STATUS("Welcome to TakeTwo\n"); STATUS("If you use these indexing results, please cite:\n"); STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); - - + tp = malloc(sizeof(struct taketwo_private)); if ( tp == NULL ) return NULL; - + tp->ltl = ltl; tp->cell = cell; tp->indm = *indm; - + return (IndexingPrivate *)tp; } -- cgit v1.2.3 From 8f14feabfd85a73a747051c5f77443ed6b65c7c2 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 18 May 2017 14:30:45 +0200 Subject: Formatting --- libcrystfel/src/taketwo.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 08b78af4..54741bd2 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -556,8 +556,8 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, * ------------------------------------------------------------------------*/ static signed int finalise_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, - int *obs_members, int *match_members, - int member_num) + int *obs_members, int *match_members, + int member_num) { gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); @@ -963,7 +963,7 @@ static int generate_rotation_sym_ops(TakeTwoCell *ttCell) SymOpList rawList; switch (lattice) { - case L_TRICLINIC: + case L_TRICLINIC: // ...get parental guidance for unusually accurate candidness? rawList = getpg_uac("1"); break; @@ -985,7 +985,7 @@ static int generate_rotation_sym_ops(TakeTwoCell *ttCell) case L_CUBIC: rawList = getpg_uac("432"); break; - default: + default: break; } @@ -1269,7 +1269,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) int success = generate_rotation_sym_ops(&ttCell); int threshold_reached = find_seed(obs_vecs, obs_vec_count, - &solution, cell); + &solution, cell); if ( solution == NULL ) { cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); -- cgit v1.2.3 From 9d798b597f0a8ff93387c65d5f5124d7329aba83 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 18 May 2017 14:30:59 +0200 Subject: Small fixes --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 54741bd2..e99e3dca 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -812,11 +812,11 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, int **her_match_idxs, int **his_match_idxs, int *match_count, struct TakeTwoCell *cell) { - gsl_matrix **old_mats = calloc(sizeof(gsl_matrix *) * match_count); int num_occupied = 0; + gsl_matrix **old_mats = calloc(*match_count, sizeof(gsl_matrix *)); signed int i, j; - for (i = match_count - 1; i >= 0; i++) { + for (i = *match_count - 1; i >= 0; i++) { int her_match = (*her_match_idxs)[i]; int his_match = (*his_match_idxs)[i]; @@ -957,7 +957,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, return (best_rotation != NULL); } -static int generate_rotation_sym_ops(TakeTwoCell *ttCell) +static int generate_rotation_sym_ops(struct TakeTwoCell *ttCell) { LatticeType lattice = cell_get_lattice_type(ttCell->cell); SymOpList rawList; -- cgit v1.2.3 From 68ecea6c609544db3086a146c3ead2c91aa1cb76 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 18 May 2017 14:55:39 +0200 Subject: Implement get_chiral_holohedry() --- libcrystfel/src/taketwo.c | 96 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index e99e3dca..8751d6d1 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -957,38 +957,94 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, return (best_rotation != NULL); } -static int generate_rotation_sym_ops(struct TakeTwoCell *ttCell) + +static char *add_ua(const char *inp, char ua) { - LatticeType lattice = cell_get_lattice_type(ttCell->cell); - SymOpList rawList; + char *pg = malloc(64); + if ( pg == NULL ) return NULL; + snprintf(pg, 63, "%s_ua%c", inp, ua); + return pg; +} - switch (lattice) { + +static char *get_chiral_holohedry(UnitCell *cell) +{ + LatticeType lattice = cell_get_lattice_type(cell); + char *pg = malloc(64); + char *pgout; + + if ( pg == NULL ) return NULL; + + switch (lattice) + { case L_TRICLINIC: - // ...get parental guidance for unusually accurate candidness? - rawList = getpg_uac("1"); - break; + pg = "1"; + break; + case L_MONOCLINIC: - rawList = getpg_uac("2"); - break; + pg = "2"; + break; + case L_ORTHORHOMBIC: - rawList = getpg_uac("222"); - break; + pg = "222"; + break; + case L_TETRAGONAL: - rawList = getpg_uac("422"); - break; + pg = "422"; + break; + case L_RHOMBOHEDRAL: - rawList = getpg_uac("312_H"); // uhmmm, sure? - break; + pg = "3_R"; + break; + case L_HEXAGONAL: - rawList = getpg_uac("622"); - break; + if ( cell_get_centering(cell) == 'H' ) { + pg = "3_H"; + } else { + pg = "622"; + } + break; + + case L_CUBIC: + pg = "432"; + break; + + default: + pg = "error"; + break; + } + + switch (lattice) + { + case L_TRICLINIC: + case L_ORTHORHOMBIC: + case L_RHOMBOHEDRAL: case L_CUBIC: - rawList = getpg_uac("432"); - break; + pgout = strdup(pg); + break; + + case L_MONOCLINIC: + case L_TETRAGONAL: + case L_HEXAGONAL: + pgout = add_ua(pg, cell_get_unique_axis(cell)); + break; + default: - break; + break; } + return pgout; +} + + +static int generate_rotation_sym_ops(struct TakeTwoCell *ttCell) +{ + SymOpList *rawList; + + char *pg = get_chiral_holohedry(ttCell->cell); + rawList = get_pointgroup(pg); + free(pg); + /* Now we must convert these into rotation matrices rather than hkl * transformations (affects triclinic, monoclinic, rhombohedral and * hexagonal space groups only) */ -- cgit v1.2.3 From 185484f94e6b5dbabad8d72c0ade8f2d6cd570ab Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 14 Jun 2017 14:29:52 +0100 Subject: Added symmetry checking - better indexing rate but something's holding back a number of crystals --- libcrystfel/src/taketwo.c | 572 ++++++++++++++++++++++++++++++---------------- 1 file changed, 374 insertions(+), 198 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 8751d6d1..791af586 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -71,6 +71,8 @@ struct SpotVec struct rvec obsvec; struct rvec *matches; int match_num; + struct rvec *asym_matches; + int asym_match_num; double distance; struct rvec *her_rlp; struct rvec *his_rlp; @@ -100,19 +102,19 @@ struct TakeTwoCell #define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (20) +#define NETWORK_MEMBER_THRESHOLD (30) /* Maximum network members (obviously a solution so should stop) */ -#define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 5) +#define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (5) +#define MAX_DEAD_ENDS (10) /* Tolerance for two angles to be considered the same */ -#define ANGLE_TOLERANCE (deg2rad(3.0)) +#define ANGLE_TOLERANCE (deg2rad(0.7)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(3.0)) +#define TRACE_TOLERANCE (deg2rad(5.0)) /** TODO: * @@ -316,10 +318,94 @@ static double matrix_trace(gsl_matrix *a) return tr; } -static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, - struct TakeTwoCell *cell) +static char *add_ua(const char *inp, char ua) +{ + char *pg = malloc(64); + if ( pg == NULL ) return NULL; + snprintf(pg, 63, "%s_ua%c", inp, ua); + return pg; +} + + +static char *get_chiral_holohedry(UnitCell *cell) +{ + LatticeType lattice = cell_get_lattice_type(cell); + char *pg = malloc(64); + char *pgout = 0; + + if ( pg == NULL ) return NULL; + + switch (lattice) + { + case L_TRICLINIC: + pg = "1"; + break; + + case L_MONOCLINIC: + pg = "2"; + break; + + case L_ORTHORHOMBIC: + pg = "222"; + break; + + case L_TETRAGONAL: + pg = "422"; + break; + + case L_RHOMBOHEDRAL: + pg = "3_R"; + break; + + case L_HEXAGONAL: + if ( cell_get_centering(cell) == 'H' ) { + pg = "3_H"; + } else { + pg = "622"; + } + break; + + case L_CUBIC: + pg = "432"; + break; + + default: + pg = "error"; + break; + } + + switch (lattice) + { + case L_TRICLINIC: + case L_ORTHORHOMBIC: + case L_RHOMBOHEDRAL: + case L_CUBIC: + pgout = strdup(pg); + break; + + case L_MONOCLINIC: + case L_TETRAGONAL: + case L_HEXAGONAL: + pgout = add_ua(pg, cell_get_unique_axis(cell)); + break; + + default: + break; + } + + return pgout; +} + + +static SymOpList *sym_ops_for_cell(UnitCell *cell) { + SymOpList *rawList; + char *pg = get_chiral_holohedry(cell); + rawList = get_pointgroup(pg); + free(pg); + + return rawList; } static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, @@ -346,6 +432,27 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, return (tr < max); } +static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, + struct TakeTwoCell *cell) +{ + int i; + + for (i = 0; i < cell->numOps; i++) { + gsl_matrix *testRot = gsl_matrix_alloc(3, 3); + gsl_matrix *symOp = cell->rotSymOps[i]; + + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, rot1, symOp, + 0.0, testRot); + + if (rot_mats_are_similar(testRot, rot2, NULL)) { + return 1; + } + + gsl_matrix_free(testRot); + } + + return 0; +} static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) { @@ -469,6 +576,9 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, int i, j; *match_count = 0; + double min_angle = deg2rad(2.5); + double max_angle = deg2rad(187.5); + // *her_match_idx = -1; // *his_match_idx = -1; @@ -478,49 +588,57 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, /* calculate angle between all potential theoretical vectors */ for ( i=0; imatch_num; i++ ) { - for ( j=0; jmatch_num; j++ ) { - - struct rvec *her_match = &her_obs->matches[i]; - struct rvec *his_match = &his_obs->matches[j]; - - double theory_angle = rvec_angle(*her_match, - *his_match); - - /* is this angle a match? */ + for ( j=0; jmatch_num; j++ ) { - double angle_diff = fabs(theory_angle - obs_angle); + struct rvec *her_match = &her_obs->matches[i]; + struct rvec *his_match = &his_obs->matches[j]; - if ( angle_diff < ANGLE_TOLERANCE ) { - size_t new_size = (*match_count + 1) * - sizeof(int); - if (her_match_idxs && his_match_idxs) - { - /* Reallocate the array to fit in another match */ - int *temp_hers; - temp_hers = realloc(*her_match_idxs, new_size); - int *temp_his; - temp_his = realloc(*his_match_idxs, new_size); + double theory_angle = rvec_angle(*her_match, + *his_match); - if ( temp_hers == NULL || temp_his == NULL ) { - apologise(); - } + /* is this angle a match? */ + + /* If the angles are too close to 0 + or 180, one axis ill-determined */ + if (theory_angle < min_angle || + theory_angle > max_angle) { + continue; + } - (*her_match_idxs) = temp_hers; - (*his_match_idxs) = temp_his; + double angle_diff = fabs(theory_angle - obs_angle); - (*her_match_idxs)[*match_count] = i; - (*his_match_idxs)[*match_count] = j; + if ( angle_diff < ANGLE_TOLERANCE ) { + + size_t new_size = (*match_count + 1) * + sizeof(int); + if (her_match_idxs && his_match_idxs) + { + /* Reallocate the array to fit in another match */ + int *temp_hers; + temp_hers = realloc(*her_match_idxs, new_size); + int *temp_his; + temp_his = realloc(*his_match_idxs, new_size); + + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); } - (*match_count)++; + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; + + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; } + + (*match_count)++; } } + } return (*match_count > 0); } - +// DELETE ME IF UNUSED static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, int *obs_members, int *match_members, int num) { @@ -530,7 +648,7 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, * is identical - too much faff. **/ - int i, j; + int i = 0; struct SpotVec *her_obs = &obs_vecs[test_idx]; for ( i=0; i *max_members) { *max_members = member_num; } @@ -777,10 +896,23 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, /* If member_num is high enough, we want to return a yes */ if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } + + /* + int i; + for (i = 0; i < member_num; i++) + { + STATUS("."); + } - finalise_solution(rot, obs_vecs, obs_members, - match_members, member_num); + if ( member_num > NETWORK_MEMBER_THRESHOLD ) { + STATUS(" yes (%i)\n", member_num); + } else { + STATUS(" nope (%i)\n", member_num); + }*/ + finish_solution(rot, obs_vecs, obs_members, + match_members, member_num); + return ( member_num > NETWORK_MEMBER_THRESHOLD ); } @@ -808,18 +940,26 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, } static int weed_duplicate_matches(struct SpotVec *her_obs, - struct SpotVec *his_obs, - int **her_match_idxs, int **his_match_idxs, - int *match_count, struct TakeTwoCell *cell) + struct SpotVec *his_obs, + int **her_match_idxs, int **his_match_idxs, + int *match_count, struct TakeTwoCell *cell) { int num_occupied = 0; gsl_matrix **old_mats = calloc(*match_count, sizeof(gsl_matrix *)); + if (old_mats == NULL) + { + apologise(); + return 0; + } + signed int i, j; - for (i = *match_count - 1; i >= 0; i++) { + int duplicates = 0; + + for (i = *match_count - 1; i >= 0; i--) { int her_match = (*her_match_idxs)[i]; int his_match = (*his_match_idxs)[i]; - + struct rvec i_obsvec = her_obs->obsvec; struct rvec j_obsvec = his_obs->obsvec; struct rvec i_cellvec = her_obs->matches[her_match]; @@ -828,6 +968,8 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, i_cellvec, j_cellvec); + int found = 0; + for (j = 0; j < num_occupied; j++) { if (old_mats[j] && symm_rot_mats_are_similar(old_mats[j], mat, cell)) @@ -835,16 +977,21 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, // we have found a duplicate, so flag as bad. (*her_match_idxs)[i] = -1; (*his_match_idxs)[i] = -1; + found = 1; + + duplicates++; gsl_matrix_free(mat); - } else { - // we have not found a duplicate, add to list. - old_mats[num_occupied] = mat; - num_occupied++; } } + + if (!found) { + // we have not found a duplicate, add to list. + old_mats[num_occupied] = mat; + num_occupied++; + } } - + for (i = 0; i < num_occupied; i++) { if (old_mats[i]) { gsl_matrix_free(old_mats[i]); @@ -852,6 +999,8 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, } free(old_mats); + + return 1; } static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, @@ -861,7 +1010,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, int max_max_members = 0; gsl_matrix *best_rotation = NULL; - unsigned long start_time = time(NULL); +// unsigned long start_time = time(NULL); /* loop round pairs of vectors to try and find a suitable * seed to start building a self-consistent network of vectors @@ -885,7 +1034,10 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, int *i_idx = 0; int *j_idx = 0; int matches; - + + // double dist1Pc = 100 * obs_vecs[i].distance / MAX_RECIP_DISTANCE; +// double dist2Pc = 100 * obs_vecs[j].distance / MAX_RECIP_DISTANCE; + /* Check to see if any angles match from the cell vectors */ obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j], &i_idx, &j_idx, &matches); @@ -932,8 +1084,8 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, } } - unsigned long now_time = time(NULL); - unsigned int seconds = now_time - start_time; +// unsigned long now_time = time(NULL); +// unsigned int seconds = now_time - start_time; // Commented out for the time being. /* @@ -957,121 +1109,96 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, return (best_rotation != NULL); } - -static char *add_ua(const char *inp, char ua) -{ - char *pg = malloc(64); - if ( pg == NULL ) return NULL; - snprintf(pg, 63, "%s_ua%c", inp, ua); - return pg; -} - - -static char *get_chiral_holohedry(UnitCell *cell) +static void set_gsl_matrix(gsl_matrix *mat, double asx, double asy, double asz, + double bsx, double bsy, double bsz, + double csx, double csy, double csz) { - LatticeType lattice = cell_get_lattice_type(cell); - char *pg = malloc(64); - char *pgout; - - if ( pg == NULL ) return NULL; - - switch (lattice) - { - case L_TRICLINIC: - pg = "1"; - break; - - case L_MONOCLINIC: - pg = "2"; - break; - - case L_ORTHORHOMBIC: - pg = "222"; - break; - - case L_TETRAGONAL: - pg = "422"; - break; - - case L_RHOMBOHEDRAL: - pg = "3_R"; - break; - - case L_HEXAGONAL: - if ( cell_get_centering(cell) == 'H' ) { - pg = "3_H"; - } else { - pg = "622"; - } - break; - - case L_CUBIC: - pg = "432"; - break; - - default: - pg = "error"; - break; - } - - switch (lattice) - { - case L_TRICLINIC: - case L_ORTHORHOMBIC: - case L_RHOMBOHEDRAL: - case L_CUBIC: - pgout = strdup(pg); - break; - - case L_MONOCLINIC: - case L_TETRAGONAL: - case L_HEXAGONAL: - pgout = add_ua(pg, cell_get_unique_axis(cell)); - break; - - default: - break; - } - - return pgout; + gsl_matrix_set(mat, 0, 0, asx); + gsl_matrix_set(mat, 0, 1, asy); + gsl_matrix_set(mat, 0, 2, asz); + gsl_matrix_set(mat, 1, 0, bsx); + gsl_matrix_set(mat, 1, 1, bsy); + gsl_matrix_set(mat, 1, 2, bsz); + gsl_matrix_set(mat, 2, 0, csx); + gsl_matrix_set(mat, 2, 1, csy); + gsl_matrix_set(mat, 2, 2, csz); } - static int generate_rotation_sym_ops(struct TakeTwoCell *ttCell) { - SymOpList *rawList; - - char *pg = get_chiral_holohedry(ttCell->cell); - rawList = get_pointgroup(pg); - free(pg); + SymOpList *rawList = sym_ops_for_cell(ttCell->cell); /* Now we must convert these into rotation matrices rather than hkl * transformations (affects triclinic, monoclinic, rhombohedral and * hexagonal space groups only) */ + + double asx, asy, asz; + double bsx, bsy, bsz; + double csx, csy, csz; + gsl_matrix *recip = gsl_matrix_alloc(3, 3); + gsl_matrix *cart = gsl_matrix_alloc(3, 3); cell_get_reciprocal(ttCell->cell, &asx, &asy, &asz, &bsx, &bsy, &bsz, &csx, &csy, &csz); - inv = gsl_matrix_alloc(3, 3); - gsl_matrix_set(inv, 0, 0, asx); - gsl_matrix_set(inv, 0, 1, asy); - gsl_matrix_set(inv, 0, 2, asz); - gsl_matrix_set(inv, 1, 0, bsx); - gsl_matrix_set(inv, 1, 1, bsy); - gsl_matrix_set(inv, 1, 2, bsz); - gsl_matrix_set(inv, 2, 0, csx); - gsl_matrix_set(inv, 2, 1, csy); - gsl_matrix_set(inv, 2, 2, csz); + set_gsl_matrix(recip, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); - // FIXME: Finish me! Along the lines of: - /* - MatrixPtr newMat = matFromCCP4(&spaceGroup->symop[j]); - MatrixPtr ortho = newMat; - ortho->preMultiply(*unitCell); - ortho->multiply(*reverse); - */ + cell_get_cartesian(ttCell->cell, &asx, &asy, &asz, &bsx, &bsy, + &bsz, &csx, &csy, &csz); + + set_gsl_matrix(cart, asx, asy, asz, bsx, bsy, bsz, csx, csy, csz); + + int i, j, k; + int numOps = num_equivs(rawList, NULL); + + ttCell->rotSymOps = malloc(numOps * sizeof(gsl_matrix *)); + ttCell->numOps = numOps; + + if (ttCell->rotSymOps == NULL) { + apologise(); + return 0; + } + + for (i = 0; i < numOps; i++) + { + gsl_matrix *symOp = gsl_matrix_alloc(3, 3); + IntegerMatrix *op = get_symop(rawList, NULL, i); + + for (j = 0; j < 3; j++) { + for (k = 0; k < 3; k++) { + gsl_matrix_set(symOp, j, k, intmat_get(op, j, k)); + } + } + + gsl_matrix *first = gsl_matrix_calloc(3, 3); + gsl_matrix *second = gsl_matrix_calloc(3, 3); + + /* Each equivalence is of the form: + cartesian * symOp * reciprocal. + First multiplication: symOp * reciprocal */ + + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, + 1.0, symOp, recip, + 0.0, first); + + /* Second multiplication: cartesian * first */ + + gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, + 1.0, cart, first, + 0.0, second); + + ttCell->rotSymOps[i] = second; + + gsl_matrix_free(symOp); + gsl_matrix_free(first); + } - gsl_matrix_free(inv); + // FIXME: Finish me! Along the lines of: + + gsl_matrix_free(cart); + gsl_matrix_free(recip); + + return 1; } @@ -1090,7 +1217,8 @@ static int sort_func(const void *av, const void *bv) static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, - struct SpotVec *obs_vecs, int obs_vec_count) + struct SpotVec *obs_vecs, int obs_vec_count, + int is_asymmetric) { int i, j; @@ -1098,9 +1226,8 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, int count = 0; struct sortme *for_sort = NULL; - + for ( j=0; j Date: Wed, 14 Jun 2017 16:44:07 +0100 Subject: Memory leak fixes and various tweaks --- libcrystfel/src/taketwo.c | 121 +++++++++++++++++++++++++++++++--------------- 1 file changed, 82 insertions(+), 39 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 791af586..5e7bb73a 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -102,16 +102,16 @@ struct TakeTwoCell #define RECIP_TOLERANCE (0.001*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (30) +#define NETWORK_MEMBER_THRESHOLD (25) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (10) +#define MAX_DEAD_ENDS (2) /* Tolerance for two angles to be considered the same */ -#define ANGLE_TOLERANCE (deg2rad(0.7)) +#define ANGLE_TOLERANCE (deg2rad(0.6)) /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(5.0)) @@ -392,7 +392,7 @@ static char *get_chiral_holohedry(UnitCell *cell) default: break; } - + return pgout; } @@ -445,6 +445,7 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, 0.0, testRot); if (rot_mats_are_similar(testRot, rot2, NULL)) { + gsl_matrix_free(testRot); return 1; } @@ -534,7 +535,6 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, static int obs_vecs_share_spot(struct SpotVec *her_obs, struct SpotVec *his_obs) { - /* FIXME: Disgusting... can I tone this down a bit? */ if ( (her_obs->her_rlp == his_obs->her_rlp) || (her_obs->her_rlp == his_obs->his_rlp) || (her_obs->his_rlp == his_obs->her_rlp) || @@ -550,6 +550,9 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, int *members, int num) { int i; + int total = 0; + int target = 1; + struct SpotVec *her_obs = &obs_vecs[test_idx]; for ( i=0; i target) { + return 1; } return 0; @@ -579,9 +586,6 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, double min_angle = deg2rad(2.5); double max_angle = deg2rad(187.5); - // *her_match_idx = -1; - // *his_match_idx = -1; - /* calculate angle between observed vectors */ double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); @@ -597,26 +601,52 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, *his_match); /* is this angle a match? */ - - /* If the angles are too close to 0 - or 180, one axis ill-determined */ - if (theory_angle < min_angle || - theory_angle > max_angle) { - continue; - } double angle_diff = fabs(theory_angle - obs_angle); if ( angle_diff < ANGLE_TOLERANCE ) { + // in the case of a brief check only + if (!her_match_idxs || !his_match_idxs) { + return 1; + } + /* If the angles are too close to 0 + or 180, one axis ill-determined */ + if (theory_angle < min_angle || + theory_angle > max_angle) { + continue; + } + + // check the third vector + + struct rvec theory_diff = diff_vec(*his_match, *her_match); + struct rvec obs_diff = diff_vec(his_obs->obsvec, + her_obs->obsvec); + + theory_angle = rvec_angle(*her_match, + theory_diff); + obs_angle = rvec_angle(her_obs->obsvec, obs_diff); + + if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + continue; + } + + theory_angle = rvec_angle(*his_match, + theory_diff); + obs_angle = rvec_angle(his_obs->obsvec, obs_diff); + + if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + continue; + } + size_t new_size = (*match_count + 1) * sizeof(int); if (her_match_idxs && his_match_idxs) { /* Reallocate the array to fit in another match */ int *temp_hers; - temp_hers = realloc(*her_match_idxs, new_size); int *temp_his; + temp_hers = realloc(*her_match_idxs, new_size); temp_his = realloc(*his_match_idxs, new_size); if ( temp_hers == NULL || temp_his == NULL ) { @@ -644,14 +674,12 @@ static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, { /* note: this is just a preliminary check to reduce unnecessary * computation later down the line, but is not entirely accurate. - * For example, I have not checked that the 'matching cell vector' - * is identical - too much faff. **/ int i = 0; struct SpotVec *her_obs = &obs_vecs[test_idx]; - for ( i=0; inumOps; i++ ) { + gsl_matrix_free(ttCell->rotSymOps[i]); + } + + free(ttCell->rotSymOps); +} + /* ------------------------------------------------------------------------ * external functions - top level functions (Level 1) @@ -1495,7 +1532,8 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) success = match_obs_to_cell_vecs(cell_vecs, cell_vec_count, obs_vecs, obs_vec_count, 0); - cleanup_taketwo_cell_vecs(cell_vecs); + free(cell_vecs); + free(asym_vecs); if ( !success ) return NULL; @@ -1511,6 +1549,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) result = transform_cell_gsl(cell, solution); gsl_matrix_free(solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); + cleanup_taketwo_cell(&ttCell); return result; } @@ -1590,9 +1629,13 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, return NULL; } - STATUS("Welcome to TakeTwo\n"); - STATUS("If you use these indexing results, please cite:\n"); + STATUS("************************************\n"); + STATUS("***** Welcome to TakeTwo *****\n"); + STATUS("************************************\n\n"); + STATUS("If you use these indexing results, please keep a roof\n"); + STATUS("over my head by citing:\n"); STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); + STATUS("\n"); tp = malloc(sizeof(struct taketwo_private)); if ( tp == NULL ) return NULL; -- cgit v1.2.3 From 973e12f7c2fe76770e969c87f51155eb7515d574 Mon Sep 17 00:00:00 2001 From: Helen Ginn Date: Wed, 14 Jun 2017 17:05:29 +0100 Subject: More fiddling --- libcrystfel/src/taketwo.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 5e7bb73a..ff7a9f41 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -99,7 +99,7 @@ struct TakeTwoCell #define MAX_RECIP_DISTANCE (0.20*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ -#define RECIP_TOLERANCE (0.001*1e10) +#define RECIP_TOLERANCE (0.0010*1e10) /* Threshold for network members to consider a potential solution */ #define NETWORK_MEMBER_THRESHOLD (25) @@ -108,13 +108,13 @@ struct TakeTwoCell #define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (2) +#define MAX_DEAD_ENDS (0) /* Tolerance for two angles to be considered the same */ -#define ANGLE_TOLERANCE (deg2rad(0.6)) +#define ANGLE_TOLERANCE (deg2rad(0.5)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(5.0)) +#define TRACE_TOLERANCE (deg2rad(4.0)) /** TODO: * @@ -761,12 +761,11 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int obs_vec_count, int *obs_members, int *match_members, int start, int member_num, - int *match_found, int match_start) + int *match_found) { int i; - int max = match_members[1] + 1000; - for ( i=start; i Date: Mon, 19 Jun 2017 17:20:07 +0200 Subject: Theoretical speed improvements by replacing acos with comparison of cosines for the quick check, but not necessarily good --- libcrystfel/src/taketwo.c | 84 +++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index ff7a9f41..a3c9efb0 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -112,6 +112,7 @@ struct TakeTwoCell /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(0.5)) +#define COSINE_TOLERANCE 0.017 /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(4.0)) @@ -409,24 +410,19 @@ static SymOpList *sym_ops_for_cell(UnitCell *cell) } static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, + gsl_matrix *sub, gsl_matrix *mul, double *score) { double tr; - gsl_matrix *sub; - gsl_matrix *mul; - sub = gsl_matrix_calloc(3, 3); gsl_matrix_memcpy(sub, rot1); gsl_matrix_sub(sub, rot2); /* sub = rot1 - rot2 */ - mul = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasNoTrans, CblasTrans, 1.0, sub, sub, 0.0, mul); tr = matrix_trace(mul); if (score != NULL) *score = tr; - gsl_matrix_free(mul); - gsl_matrix_free(sub); double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); return (tr < max); @@ -437,6 +433,11 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, { int i; + gsl_matrix *sub; + gsl_matrix *mul; + sub = gsl_matrix_calloc(3, 3); + mul = gsl_matrix_calloc(3, 3); + for (i = 0; i < cell->numOps; i++) { gsl_matrix *testRot = gsl_matrix_alloc(3, 3); gsl_matrix *symOp = cell->rotSymOps[i]; @@ -444,14 +445,19 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, rot1, symOp, 0.0, testRot); - if (rot_mats_are_similar(testRot, rot2, NULL)) { - gsl_matrix_free(testRot); + if (rot_mats_are_similar(testRot, rot2, sub, mul, NULL)) { + gsl_matrix_free(testRot); + gsl_matrix_free(sub); + gsl_matrix_free(mul); return 1; } gsl_matrix_free(testRot); } + gsl_matrix_free(sub); + gsl_matrix_free(mul); + return 0; } @@ -583,11 +589,11 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, int i, j; *match_count = 0; - double min_angle = deg2rad(2.5); - double max_angle = deg2rad(187.5); + double min_angle = 0.9990; + double max_angle = -0.99144; /* calculate angle between observed vectors */ - double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); + double obs_cos = rvec_cosine(her_obs->obsvec, his_obs->obsvec); /* calculate angle between all potential theoretical vectors */ @@ -597,14 +603,14 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, struct rvec *her_match = &her_obs->matches[i]; struct rvec *his_match = &his_obs->matches[j]; - double theory_angle = rvec_angle(*her_match, - *his_match); + double theory_cos = rvec_cosine(*her_match, + *his_match); /* is this angle a match? */ - double angle_diff = fabs(theory_angle - obs_angle); + double cos_diff = fabs(theory_cos - obs_cos); - if ( angle_diff < ANGLE_TOLERANCE ) { + if ( cos_diff < COSINE_TOLERANCE ) { // in the case of a brief check only if (!her_match_idxs || !his_match_idxs) { return 1; @@ -612,32 +618,32 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, /* If the angles are too close to 0 or 180, one axis ill-determined */ - if (theory_angle < min_angle || - theory_angle > max_angle) { + if (theory_cos > min_angle || + theory_cos < max_angle) { continue; } // check the third vector - + /* struct rvec theory_diff = diff_vec(*his_match, *her_match); struct rvec obs_diff = diff_vec(his_obs->obsvec, her_obs->obsvec); - theory_angle = rvec_angle(*her_match, + theory_cos = rvec_cosine(*her_match, theory_diff); - obs_angle = rvec_angle(her_obs->obsvec, obs_diff); + obs_cos = rvec_cosine(her_obs->obsvec, obs_diff); - if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + if (fabs(obs_cos - theory_cos) > COSINE_TOLERANCE) { continue; } - theory_angle = rvec_angle(*his_match, + theory_cos = rvec_cosine(*his_match, theory_diff); - obs_angle = rvec_angle(his_obs->obsvec, obs_diff); + obs_cos = rvec_cosine(his_obs->obsvec, obs_diff); - if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + if (fabs(obs_cos - theory_cos) > COSINE_TOLERANCE) { continue; - } + }*/ size_t new_size = (*match_count + 1) * sizeof(int); @@ -705,6 +711,11 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, int *obs_members, int *match_members, int member_num) { + gsl_matrix *sub; + gsl_matrix *mul; + sub = gsl_matrix_calloc(3, 3); + mul = gsl_matrix_calloc(3, 3); + gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); int i, j, count; @@ -736,6 +747,7 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, for (j=0; j Date: Mon, 19 Jun 2017 17:23:31 +0200 Subject: Compile error sorted and some code re-added --- libcrystfel/src/taketwo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index a3c9efb0..d42b2c13 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -624,7 +624,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, } // check the third vector - /* + struct rvec theory_diff = diff_vec(*his_match, *her_match); struct rvec obs_diff = diff_vec(his_obs->obsvec, her_obs->obsvec); @@ -643,7 +643,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, if (fabs(obs_cos - theory_cos) > COSINE_TOLERANCE) { continue; - }*/ + } size_t new_size = (*match_count + 1) * sizeof(int); @@ -795,7 +795,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, /* now we check that angles between all vectors match */ // int matches = obs_angles_match_array(obs_vecs, i, obs_members, - // match_members, member_num); + //match_members, member_num); // if ( !matches ) continue; -- cgit v1.2.3 From 15cf933a03cedf21257272b9c938179f97c59ce3 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Mon, 19 Jun 2017 17:27:04 +0200 Subject: Add observed angle check back in... --- libcrystfel/src/taketwo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index d42b2c13..4a6e484c 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -794,8 +794,8 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if ( !shared ) continue; /* now we check that angles between all vectors match */ - // int matches = obs_angles_match_array(obs_vecs, i, obs_members, - //match_members, member_num); + int matches = obs_angles_match_array(obs_vecs, i, obs_members, + match_members, member_num); // if ( !matches ) continue; -- cgit v1.2.3 From 242e756dcb83321121af8cb434ebf57777e68470 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Mon, 19 Jun 2017 17:28:59 +0200 Subject: Changing cosine of angle to be most sensitive to 0.5 degrees --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 4a6e484c..cc3d83f0 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -112,7 +112,7 @@ struct TakeTwoCell /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(0.5)) -#define COSINE_TOLERANCE 0.017 +#define COSINE_TOLERANCE 0.010 /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(4.0)) -- cgit v1.2.3 From 9b110b965ce64bcbf24af9a2336533522394a887 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Mon, 19 Jun 2017 17:47:00 +0200 Subject: Reduced amount of gsl_matrix reallocation --- libcrystfel/src/taketwo.c | 74 ++++++++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index cc3d83f0..c9314395 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -108,7 +108,7 @@ struct TakeTwoCell #define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (0) +#define MAX_DEAD_ENDS (1) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(0.5)) @@ -227,12 +227,11 @@ static void show_rvec(struct rvec r2) * functions called under the core functions, still specialised (Level 3) * ------------------------------------------------------------------------*/ -static gsl_matrix *rotation_around_axis(struct rvec c, double th) +static gsl_matrix *rotation_around_axis(struct rvec c, double th, + gsl_matrix *res) { double omc = 1.0 - cos(th); double s = sin(th); - gsl_matrix *res = gsl_matrix_alloc(3, 3); - gsl_matrix_set(res, 0, 0, cos(th) + c.u*c.u*omc); gsl_matrix_set(res, 0, 1, c.u*c.v*omc - c.w*s); gsl_matrix_set(res, 0, 2, c.u*c.w*omc + c.v*s); @@ -253,7 +252,7 @@ static gsl_matrix *rotation_around_axis(struct rvec c, double th) * that @result has already been allocated. Will upload the maths to the * shared Google drive. */ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, - struct rvec axis) + struct rvec axis, gsl_matrix *twizzle) { /* Let's have unit vectors */ normalise_rvec(&vec1); @@ -303,7 +302,7 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, /* Return an identity matrix which has been rotated by * theta around "axis" */ - return rotation_around_axis(axis, bestAngle); + rotation_around_axis(axis, bestAngle, twizzle); } @@ -461,12 +460,13 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, return 0; } -static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b) +static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b, + gsl_matrix *twizzle) { double th = rvec_angle(a, b); struct rvec c = rvec_cross(a, b); normalise_rvec(&c); - return rotation_around_axis(c, th); + rotation_around_axis(c, th, twizzle); } @@ -495,10 +495,9 @@ struct rvec gsl_to_rvec(gsl_vector *a) * intensive on the number crunching side so simple angle checks are used * to 'pre-scan' vectors beforehand. */ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, - struct rvec cell1, struct rvec cell2) + struct rvec cell1, struct rvec cell2, + gsl_matrix *twiz1, gsl_matrix *twiz2) { - gsl_matrix *rotateSpotDiffMatrix; - gsl_matrix *secondTwizzleMatrix; gsl_matrix *fullMat; gsl_vector *cell2v = rvec_to_gsl(cell2); gsl_vector *cell2vr = gsl_vector_calloc(3); @@ -510,30 +509,28 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Rotate reciprocal space so that the first simulated vector lines up * with the observed vector. */ - rotateSpotDiffMatrix = rotation_between_vectors(cell1, obs1); + rotation_between_vectors(cell1, obs1, twiz1); normalise_rvec(&obs1); /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, rotateSpotDiffMatrix, cell2v, + gsl_blas_dgemv(CblasNoTrans, 1.0, twiz1, cell2v, 0.0, cell2vr); /* Now we twirl around the firstAxisUnit until the rotated simulated * vector matches the second observed vector as closely as possible. */ - secondTwizzleMatrix = closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1); + closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1, twiz2); /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ fullMat = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, - rotateSpotDiffMatrix, secondTwizzleMatrix, 0.0, fullMat); + twiz1, twiz2, 0.0, fullMat); gsl_matrix_transpose(fullMat); gsl_vector_free(cell2v); gsl_vector_free(cell2vr); - gsl_matrix_free(secondTwizzleMatrix); - gsl_matrix_free(rotateSpotDiffMatrix); return fullMat; } @@ -711,11 +708,12 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, int *obs_members, int *match_members, int member_num) { - gsl_matrix *sub; - gsl_matrix *mul; - sub = gsl_matrix_calloc(3, 3); - mul = gsl_matrix_calloc(3, 3); + gsl_matrix *sub = gsl_matrix_calloc(3, 3); + gsl_matrix *mul = gsl_matrix_calloc(3, 3); + gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); + gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); + gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); int i, j, count; @@ -733,7 +731,8 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, struct rvec j_cellvec = j_vec.matches[match_members[j]]; rotations[count] = generate_rot_mat(i_obsvec, j_obsvec, - i_cellvec, j_cellvec); + i_cellvec, j_cellvec, + twiz1, twiz2); count++; } @@ -768,6 +767,8 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, free(rotations); gsl_matrix_free(sub); gsl_matrix_free(mul); + gsl_matrix_free(twiz1); + gsl_matrix_free(twiz2); return 1; } @@ -783,7 +784,9 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, gsl_matrix *mul; sub = gsl_matrix_calloc(3, 3); mul = gsl_matrix_calloc(3, 3); - + gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); + gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); + for ( i=start; imatches[his_match]; gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, - i_cellvec, j_cellvec); + i_cellvec, j_cellvec, + twiz1, twiz2); int found = 0; @@ -1056,6 +1073,9 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, free(old_mats); + gsl_matrix_free(twiz1); + gsl_matrix_free(twiz2); + return 1; } -- cgit v1.2.3 From 6ebf72a7fb71e68329ed2591a1f5858699026af6 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Thu, 29 Jun 2017 16:36:22 +0100 Subject: Relaxation of tolerances --- libcrystfel/src/taketwo.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index c9314395..1a76614c 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -108,10 +108,11 @@ struct TakeTwoCell #define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (1) +#define MAX_DEAD_ENDS (2) /* Tolerance for two angles to be considered the same */ -#define ANGLE_TOLERANCE (deg2rad(0.5)) +#define ANGLE_TOLERANCE (deg2rad(0.6)) + #define COSINE_TOLERANCE 0.010 /* Tolerance for rot_mats_are_similar */ -- cgit v1.2.3 From 6d07a1b35e83ce5bd803702a7c083365bf14efd0 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Thu, 29 Jun 2017 16:36:49 +0100 Subject: Should not limit to proceeding vectors only when a new spot may have been included\! --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 1a76614c..176526ba 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -789,7 +789,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); - for ( i=start; i Date: Thu, 29 Jun 2017 16:37:21 +0100 Subject: Disable a check which wasn't acted upon to measure impact on speed --- libcrystfel/src/taketwo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 176526ba..d1f2b9b8 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -798,8 +798,8 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if ( !shared ) continue; /* now we check that angles between all vectors match */ - int matches = obs_angles_match_array(obs_vecs, i, obs_members, - match_members, member_num); + // int matches = obs_angles_match_array(obs_vecs, i, obs_members, + // match_members, member_num); // if ( !matches ) continue; -- cgit v1.2.3 From b607e63263265edfbe4e2b7784d9da7a283b850f Mon Sep 17 00:00:00 2001 From: cppxfel Date: Thu, 29 Jun 2017 19:09:20 +0100 Subject: WARNING - profanity - uploading to my server so I can gvalgrind --- libcrystfel/src/taketwo.c | 302 +++++++++++++++++++++++++--------------------- 1 file changed, 166 insertions(+), 136 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index d1f2b9b8..b37fc8f1 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -774,21 +774,84 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, return 1; } +static int weed_duplicate_matches(struct SpotVec *her_obs, + struct SpotVec *his_obs, + int **her_match_idxs, int **his_match_idxs, + int *match_count, struct TakeTwoCell *cell) +{ + int num_occupied = 0; + gsl_matrix **old_mats = calloc(*match_count, sizeof(gsl_matrix *)); + gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); + gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); + + if (old_mats == NULL) + { + apologise(); + return 0; + } + + signed int i, j; + int duplicates = 0; + + for (i = *match_count - 1; i >= 0; i--) { + int her_match = (*her_match_idxs)[i]; + int his_match = (*his_match_idxs)[i]; + + struct rvec i_obsvec = her_obs->obsvec; + struct rvec j_obsvec = his_obs->obsvec; + struct rvec i_cellvec = her_obs->matches[her_match]; + struct rvec j_cellvec = his_obs->matches[his_match]; + + gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, + i_cellvec, j_cellvec, + twiz1, twiz2); + + int found = 0; + + for (j = 0; j < num_occupied; j++) { + if (old_mats[j] && + symm_rot_mats_are_similar(old_mats[j], mat, cell)) + { + // we have found a duplicate, so flag as bad. + (*her_match_idxs)[i] = -1; + (*his_match_idxs)[i] = -1; + found = 1; + + duplicates++; + + gsl_matrix_free(mat); + } + } + + if (!found) { + // we have not found a duplicate, add to list. + old_mats[num_occupied] = mat; + num_occupied++; + } + } + + for (i = 0; i < num_occupied; i++) { + if (old_mats[i]) { + gsl_matrix_free(old_mats[i]); + } + } + + free(old_mats); + + STATUS("Found %i\n", num_occupied); + + return 1; +} + static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, int obs_vec_count, int *obs_members, int *match_members, int start, int member_num, - int *match_found) + int *match_found, struct TakeTwoCell *cell) { int i; - - gsl_matrix *sub; - gsl_matrix *mul; - sub = gsl_matrix_calloc(3, 3); - mul = gsl_matrix_calloc(3, 3); gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); - for ( i=start; iobsvec; + struct rvec you_obs = you->obsvec; - for ( j=0; jmatches[my_idxs[k]]; + struct rvec you_cell; - test_rot = generate_rot_mat(obs_vecs[idx_k].obsvec, - obs_vecs[i].obsvec, - member_match, - a_match, - twiz1, twiz2); + you_cell = you->matches[your_idxs[k]]; + + test_rot = generate_rot_mat(me_obs, + you_obs, me_cell, you_cell, + twiz1, twiz2); double trace = 0; int ok = rot_mats_are_similar(rot, test_rot, - sub, mul, - &trace); + twiz1, twiz2, &trace); + gsl_matrix_free(test_rot); + STATUS("5\n"); + if (!ok) { all_ok = 0; + STATUS("fuck\n"); + break; } - - } - - if (all_ok) { - *match_found = test_idx[j]; - free(member_idx); - free(test_idx); - gsl_matrix_free(sub); - gsl_matrix_free(mul); - gsl_matrix_free(twiz1); - gsl_matrix_free(twiz2); - - return i; } + + free(my_idxs); + free(your_idxs); } - - free(member_idx); member_idx = NULL; - free(test_idx); member_idx = NULL; - - } - gsl_matrix_free(sub); - gsl_matrix_free(mul); - gsl_matrix_free(twiz1); - gsl_matrix_free(twiz2); + if (all_ok) { + STATUS("phew\n"); + *match_found = i; + return i; + } + } /* give up. */ @@ -887,7 +984,8 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int obs_vec_count, int obs_idx1, int obs_idx2, - int match_idx1, int match_idx2, int *max_members) + int match_idx1, int match_idx2, int *max_members, + struct TakeTwoCell *cell) { /* indices of members of the self-consistent network of vectors */ int obs_members[MAX_NETWORK_MEMBERS]; @@ -920,7 +1018,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, obs_vec_count, obs_members, match_members, start, member_num, - &match_found); + &match_found, cell); if ( member_num < 2 ) { return 0; @@ -939,6 +1037,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, start++; member_num--; dead_ends++; + STATUS("\n"); continue; } @@ -983,13 +1082,12 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, int j, int i_match, int j_match, gsl_matrix **rotation, - int *max_members) + int *max_members, struct TakeTwoCell *cell) { + gsl_matrix *rot_mat; gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); - gsl_matrix *rot_mat; - rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], @@ -999,87 +1097,15 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, /* Try to expand this rotation matrix to a larger network */ int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_match, j_match, max_members); + i, j, i_match, j_match, max_members, + cell); /* return this matrix and if it was immediately successful */ *rotation = rot_mat; - gsl_matrix_free(twiz1); - gsl_matrix_free(twiz2); return success; } -static int weed_duplicate_matches(struct SpotVec *her_obs, - struct SpotVec *his_obs, - int **her_match_idxs, int **his_match_idxs, - int *match_count, struct TakeTwoCell *cell) -{ - int num_occupied = 0; - gsl_matrix **old_mats = calloc(*match_count, sizeof(gsl_matrix *)); - - gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); - gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); - - if (old_mats == NULL) - { - apologise(); - return 0; - } - - signed int i, j; - int duplicates = 0; - - for (i = *match_count - 1; i >= 0; i--) { - int her_match = (*her_match_idxs)[i]; - int his_match = (*his_match_idxs)[i]; - - struct rvec i_obsvec = her_obs->obsvec; - struct rvec j_obsvec = his_obs->obsvec; - struct rvec i_cellvec = her_obs->matches[her_match]; - struct rvec j_cellvec = his_obs->matches[his_match]; - - gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, - i_cellvec, j_cellvec, - twiz1, twiz2); - - int found = 0; - - for (j = 0; j < num_occupied; j++) { - if (old_mats[j] && mat && - symm_rot_mats_are_similar(old_mats[j], mat, cell)) - { - // we have found a duplicate, so flag as bad. - (*her_match_idxs)[i] = -1; - (*his_match_idxs)[i] = -1; - found = 1; - - duplicates++; - } - } - - if (!found) { - // we have not found a duplicate, add to list. - old_mats[num_occupied] = mat; - num_occupied++; - } else { - gsl_matrix_free(mat); - } - } - - for (i = 0; i < num_occupied; i++) { - if (old_mats[i]) { - gsl_matrix_free(old_mats[i]); - } - } - - free(old_mats); - - gsl_matrix_free(twiz1); - gsl_matrix_free(twiz2); - - return 1; -} - static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, gsl_matrix **rotation, struct TakeTwoCell *cell) { @@ -1129,7 +1155,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, */ weed_duplicate_matches(&obs_vecs[i], &obs_vecs[j], - &i_idx, &j_idx, &matches, cell); + &i_idx, &j_idx, &matches, cell); /* We have seeds! Pass each of them through the seed-starter */ /* If a seed has the highest achieved membership, make note...*/ @@ -1141,9 +1167,11 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, int max_members = 0; - int success = start_seed(obs_vecs, obs_vec_count, i, j, + int success = start_seed(obs_vecs, obs_vec_count, + i, j, i_idx[k], j_idx[k], - rotation, &max_members); + rotation, &max_members, + cell); if (success) { free(i_idx); free(j_idx); @@ -1593,12 +1621,14 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) } // STATUS("Returning result.\n"); - + result = transform_cell_gsl(cell, solution); gsl_matrix_free(solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); cleanup_taketwo_cell(&ttCell); - + + STATUS("good.\n"); + return result; } -- cgit v1.2.3 From 0f4208d86bbf2da6ec04ca3c3867422e4ba90ace Mon Sep 17 00:00:00 2001 From: cppxfel Date: Fri, 30 Jun 2017 01:08:26 +0100 Subject: Removed some code, fixed some code, and so on and so forth --- libcrystfel/src/taketwo.c | 395 +++++++++++++++++----------------------------- 1 file changed, 146 insertions(+), 249 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index b37fc8f1..feb4ac36 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -102,19 +102,17 @@ struct TakeTwoCell #define RECIP_TOLERANCE (0.0010*1e10) /* Threshold for network members to consider a potential solution */ -#define NETWORK_MEMBER_THRESHOLD (25) +#define NETWORK_MEMBER_THRESHOLD (20) /* Maximum network members (obviously a solution so should stop) */ #define MAX_NETWORK_MEMBERS (NETWORK_MEMBER_THRESHOLD + 3) /* Maximum dead ends for a single branch extension during indexing */ -#define MAX_DEAD_ENDS (2) +#define MAX_DEAD_ENDS (10) /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(0.6)) -#define COSINE_TOLERANCE 0.010 - /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(4.0)) @@ -433,10 +431,8 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, { int i; - gsl_matrix *sub; - gsl_matrix *mul; - sub = gsl_matrix_calloc(3, 3); - mul = gsl_matrix_calloc(3, 3); + gsl_matrix *sub = gsl_matrix_calloc(3, 3); + gsl_matrix *mul = gsl_matrix_calloc(3, 3); for (i = 0; i < cell->numOps; i++) { gsl_matrix *testRot = gsl_matrix_alloc(3, 3); @@ -555,7 +551,6 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, { int i; int total = 0; - int target = 1; struct SpotVec *her_obs = &obs_vecs[test_idx]; @@ -564,143 +559,106 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, int shares = obs_vecs_share_spot(her_obs, his_obs); - if ( shares ) return 1;; - } - - if (total > target) { - return 1; + if ( shares ) return 1; } return 0; } -/** Note: this could potentially (and cautiously) converted to comparing - * cosines rather than angles, to lose an "acos" but different parts of the - * cosine graph are more sensitive than others, so may be a trade off... or not. - */ static int obs_vecs_match_angles(struct SpotVec *her_obs, - struct SpotVec *his_obs, - int **her_match_idxs, int **his_match_idxs, - int *match_count) + struct SpotVec *his_obs, + int **her_match_idxs, int **his_match_idxs, + int *match_count) { - int i, j; - *match_count = 0; - - double min_angle = 0.9990; - double max_angle = -0.99144; - - /* calculate angle between observed vectors */ - double obs_cos = rvec_cosine(her_obs->obsvec, his_obs->obsvec); - - /* calculate angle between all potential theoretical vectors */ - - for ( i=0; imatch_num; i++ ) { - for ( j=0; jmatch_num; j++ ) { - - struct rvec *her_match = &her_obs->matches[i]; - struct rvec *his_match = &his_obs->matches[j]; - - double theory_cos = rvec_cosine(*her_match, - *his_match); - - /* is this angle a match? */ - - double cos_diff = fabs(theory_cos - obs_cos); - - if ( cos_diff < COSINE_TOLERANCE ) { - // in the case of a brief check only - if (!her_match_idxs || !his_match_idxs) { - return 1; - } - - /* If the angles are too close to 0 - or 180, one axis ill-determined */ - if (theory_cos > min_angle || - theory_cos < max_angle) { - continue; - } - - // check the third vector - - struct rvec theory_diff = diff_vec(*his_match, *her_match); - struct rvec obs_diff = diff_vec(his_obs->obsvec, - her_obs->obsvec); - - theory_cos = rvec_cosine(*her_match, - theory_diff); - obs_cos = rvec_cosine(her_obs->obsvec, obs_diff); - - if (fabs(obs_cos - theory_cos) > COSINE_TOLERANCE) { - continue; - } - - theory_cos = rvec_cosine(*his_match, - theory_diff); - obs_cos = rvec_cosine(his_obs->obsvec, obs_diff); - - if (fabs(obs_cos - theory_cos) > COSINE_TOLERANCE) { - continue; - } - - size_t new_size = (*match_count + 1) * - sizeof(int); - if (her_match_idxs && his_match_idxs) - { - /* Reallocate the array to fit in another match */ - int *temp_hers; - int *temp_his; - temp_hers = realloc(*her_match_idxs, new_size); - temp_his = realloc(*his_match_idxs, new_size); - - if ( temp_hers == NULL || temp_his == NULL ) { - apologise(); - } - - (*her_match_idxs) = temp_hers; - (*his_match_idxs) = temp_his; - - (*her_match_idxs)[*match_count] = i; - (*his_match_idxs)[*match_count] = j; - } - - (*match_count)++; - } - } - } - - return (*match_count > 0); + int i, j; + *match_count = 0; + + double min_angle = deg2rad(2.5); + double max_angle = deg2rad(187.5); + + /* calculate angle between observed vectors */ + double obs_angle = rvec_angle(her_obs->obsvec, his_obs->obsvec); + + /* calculate angle between all potential theoretical vectors */ + + for ( i=0; imatch_num; i++ ) { + for ( j=0; jmatch_num; j++ ) { + + struct rvec *her_match = &her_obs->matches[i]; + struct rvec *his_match = &his_obs->matches[j]; + + double theory_angle = rvec_angle(*her_match, + *his_match); + + /* is this angle a match? */ + + double angle_diff = fabs(theory_angle - obs_angle); + + if ( angle_diff < ANGLE_TOLERANCE ) { + // in the case of a brief check only + if (!her_match_idxs || !his_match_idxs) { + return 1; + } + + /* If the angles are too close to 0 + or 180, one axis ill-determined */ + if (theory_angle < min_angle || + theory_angle > max_angle) { + continue; + } + + // check the third vector + + struct rvec theory_diff = diff_vec(*his_match, *her_match); + struct rvec obs_diff = diff_vec(his_obs->obsvec, + her_obs->obsvec); + + theory_angle = rvec_angle(*her_match, + theory_diff); + obs_angle = rvec_angle(her_obs->obsvec, obs_diff); + + if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + continue; + } + + theory_angle = rvec_angle(*his_match, + theory_diff); + obs_angle = rvec_angle(his_obs->obsvec, obs_diff); + + if (fabs(obs_angle - theory_angle) > ANGLE_TOLERANCE) { + continue; + } + + size_t new_size = (*match_count + 1) * + sizeof(int); + if (her_match_idxs && his_match_idxs) + { + /* Reallocate the array to fit in another match */ + int *temp_hers; + int *temp_his; + temp_hers = realloc(*her_match_idxs, new_size); + temp_his = realloc(*his_match_idxs, new_size); + + if ( temp_hers == NULL || temp_his == NULL ) { + apologise(); + } + + (*her_match_idxs) = temp_hers; + (*his_match_idxs) = temp_his; + + (*her_match_idxs)[*match_count] = i; + (*his_match_idxs)[*match_count] = j; + } + + (*match_count)++; + } + } + } + + return (*match_count > 0); } -// DELETE ME IF UNUSED -static int obs_angles_match_array(struct SpotVec *obs_vecs, int test_idx, - int *obs_members, int *match_members, int num) -{ - /* note: this is just a preliminary check to reduce unnecessary - * computation later down the line, but is not entirely accurate. - **/ - - int i = 0; - struct SpotVec *her_obs = &obs_vecs[test_idx]; - - for ( i=0; imatches[match_members[j]]; + struct rvec me_obs = me->obsvec; struct rvec you_obs = you->obsvec; - int *your_idxs = 0; - int *my_idxs = 0; + int one_is_okay = 0; - obs_vecs_match_angles(me, you, &my_idxs, - &your_idxs, &match_num); - - STATUS("2\n"); - - if (match_num == 0) { - all_ok = 0; - STATUS("shit\n"); - continue; - } - - weed_duplicate_matches(me, you, - &my_idxs, &your_idxs, - &match_num, cell); - - STATUS("3\n"); - - for ( k=0; kmatch_num; k++ ) { + gsl_matrix *test_rot; + + struct rvec me_cell = me->matches[k]; - if (my_idxs[k] < 0 || your_idxs[k] < 0) { - continue; - } - - STATUS("4\n"); - - struct rvec me_cell = me->matches[my_idxs[k]]; - struct rvec you_cell; - - you_cell = you->matches[your_idxs[k]]; - test_rot = generate_rot_mat(me_obs, you_obs, me_cell, you_cell, twiz1, twiz2); @@ -955,23 +858,34 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, gsl_matrix_free(test_rot); - STATUS("5\n"); - - if (!ok) { - all_ok = 0; - STATUS("fuck\n"); - - break; + if (ok) { + one_is_okay = 1; + + if (matched >= 0 && k == matched) { + *match_found = k; + } else if (matched < 0) { + matched = k; + } else { + one_is_okay = 0; + break; + } } } - free(my_idxs); - free(your_idxs); + if (!one_is_okay) { + all_ok = 0; + break; + } } - + + if (all_ok) { - STATUS("phew\n"); - *match_found = i; + + for ( int j=0; j *max_members) { *max_members = member_num; } @@ -1059,19 +970,6 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, /* If member_num is high enough, we want to return a yes */ if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; } - - /* - int i; - for (i = 0; i < member_num; i++) - { - STATUS("."); - } - - if ( member_num > NETWORK_MEMBER_THRESHOLD ) { - STATUS(" yes (%i)\n", member_num); - } else { - STATUS(" nope (%i)\n", member_num); - }*/ finish_solution(rot, obs_vecs, obs_members, match_members, member_num); @@ -1620,15 +1518,11 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) return NULL; } -// STATUS("Returning result.\n"); - result = transform_cell_gsl(cell, solution); gsl_matrix_free(solution); cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); cleanup_taketwo_cell(&ttCell); - STATUS("good.\n"); - return result; } @@ -1673,8 +1567,11 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) if ( !peak_sanity_check(image, &cr, 1) ) { cell_free(cell); crystal_free(cr); + // STATUS("Rubbish!!\n"); return 0; + } else { + // STATUS("That's good!\n"); } } @@ -1711,7 +1608,7 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, STATUS("***** Welcome to TakeTwo *****\n"); STATUS("************************************\n\n"); STATUS("If you use these indexing results, please keep a roof\n"); - STATUS("over my head by citing:\n"); + STATUS("over the author's head by citing:\n"); STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); STATUS("\n"); -- cgit v1.2.3 From afec15a5577edd6dac05fef0df0600d2762402c0 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Fri, 30 Jun 2017 01:16:23 +0100 Subject: Yet more speed fiddles --- libcrystfel/src/taketwo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index feb4ac36..3b3e3084 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -96,7 +96,7 @@ struct TakeTwoCell /* Maximum distance between two rlp sizes to consider info for indexing */ -#define MAX_RECIP_DISTANCE (0.20*1e10) +#define MAX_RECIP_DISTANCE (0.15*1e10) /* Tolerance for two lengths in reciprocal space to be considered the same */ #define RECIP_TOLERANCE (0.0010*1e10) @@ -114,7 +114,7 @@ struct TakeTwoCell #define ANGLE_TOLERANCE (deg2rad(0.6)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(4.0)) +#define TRACE_TOLERANCE (deg2rad(2.5)) /** TODO: * @@ -882,9 +882,9 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if (all_ok) { for ( int j=0; j Date: Fri, 30 Jun 2017 01:17:36 +0100 Subject: Didn't use C99 code, fixing --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 3b3e3084..d20971e0 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -881,7 +881,7 @@ static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, if (all_ok) { - for ( int j=0; j Date: Fri, 30 Jun 2017 16:40:24 +0100 Subject: Removed unnecessary returns and set functions to void, and removed superfluous integer declaration --- libcrystfel/src/taketwo.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index d20971e0..aa45b268 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -213,21 +213,22 @@ static struct rvec rvec_cross(struct rvec a, struct rvec b) return c; } - +/* static void show_rvec(struct rvec r2) { struct rvec r = r2; normalise_rvec(&r); STATUS("[ %.3f %.3f %.3f ]\n", r.u, r.v, r.w); } +*/ /* ------------------------------------------------------------------------ * functions called under the core functions, still specialised (Level 3) * ------------------------------------------------------------------------*/ -static gsl_matrix *rotation_around_axis(struct rvec c, double th, - gsl_matrix *res) +static void rotation_around_axis(struct rvec c, double th, + gsl_matrix *res) { double omc = 1.0 - cos(th); double s = sin(th); @@ -240,18 +241,13 @@ static gsl_matrix *rotation_around_axis(struct rvec c, double th, gsl_matrix_set(res, 2, 0, c.w*c.u*omc - c.v*s); gsl_matrix_set(res, 2, 1, c.w*c.v*omc + c.u*s); gsl_matrix_set(res, 2, 2, cos(th) + c.w*c.w*omc); - - return res; } /* Rotate vector (vec1) around axis (axis) by angle theta. Find value of - * theta for which the angle between (vec1) and (vec2) is minimised. - * Behold! Finally an analytical solution for this one. Assuming - * that @result has already been allocated. Will upload the maths to the - * shared Google drive. */ -static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, - struct rvec axis, gsl_matrix *twizzle) + * theta for which the angle between (vec1) and (vec2) is minimised. */ +static void closest_rot_mat(struct rvec vec1, struct rvec vec2, + struct rvec axis, gsl_matrix *twizzle) { /* Let's have unit vectors */ normalise_rvec(&vec1); @@ -299,8 +295,8 @@ static gsl_matrix *closest_rot_mat(struct rvec vec1, struct rvec vec2, int addPi = (cosAlphaOther > cosAlpha); double bestAngle = theta + addPi * M_PI; - /* Return an identity matrix which has been rotated by - * theta around "axis" */ + /* Don't return an identity matrix which has been rotated by + * theta around "axis", but do assign it to twizzle. */ rotation_around_axis(axis, bestAngle, twizzle); } @@ -457,8 +453,8 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, return 0; } -static gsl_matrix *rotation_between_vectors(struct rvec a, struct rvec b, - gsl_matrix *twizzle) +static void rotation_between_vectors(struct rvec a, struct rvec b, + gsl_matrix *twizzle) { double th = rvec_angle(a, b); struct rvec c = rvec_cross(a, b); @@ -550,7 +546,6 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, int *members, int num) { int i; - int total = 0; struct SpotVec *her_obs = &obs_vecs[test_idx]; -- cgit v1.2.3 From 938f1672ad2ae66af6b5732f87b52351bb048391 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Fri, 30 Jun 2017 17:23:04 +0100 Subject: Ridiculous ASCII art to increase prominance of citation --- libcrystfel/src/taketwo.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index aa45b268..2984959f 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1599,12 +1599,23 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, return NULL; } - STATUS("************************************\n"); - STATUS("***** Welcome to TakeTwo *****\n"); - STATUS("************************************\n\n"); - STATUS("If you use these indexing results, please keep a roof\n"); - STATUS("over the author's head by citing:\n"); - STATUS("Ginn et al., Acta Cryst. (2016). D72, 956-965\n"); + STATUS("*******************************************************************\n"); + STATUS("***** Welcome to TakeTwo *****\n"); + STATUS("*******************************************************************\n"); + STATUS(" If you use these indexing results, please keep a roof\n"); + STATUS(" over the author's head by citing this paper.\n\n"); + + STATUS("o o o o o o o o o o o o\n"); + STATUS(" o o o o o o o o o o o \n"); + STATUS("o o\n"); + STATUS(" o The citation is: o \n"); + STATUS("o Ginn et al., Acta Cryst. (2016). D72, 956-965 o\n"); + STATUS(" o Thank you! o \n"); + STATUS("o o\n"); + STATUS(" o o o o o o o o o o o \n"); + STATUS("o o o o o o o o o o o o\n"); + + STATUS("\n"); tp = malloc(sizeof(struct taketwo_private)); -- cgit v1.2.3 From 4f6fdb75716cc884ce0db7ce9970574e23af3bc8 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Sat, 1 Jul 2017 13:44:53 +0100 Subject: Adding a cutoff for maximum allowed vectors (100,000) to stop Tom's computer (and others) falling apart again. --- libcrystfel/src/taketwo.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 2984959f..4cd90cd4 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -110,6 +110,10 @@ struct TakeTwoCell /* Maximum dead ends for a single branch extension during indexing */ #define MAX_DEAD_ENDS (10) +/* Maximum observed vectors before TakeTwo gives up and deals with + * what is already there. */ +#define MAX_OBS_VECTORS 100000 + /* Tolerance for two angles to be considered the same */ #define ANGLE_TOLERANCE (deg2rad(0.6)) @@ -1291,7 +1295,7 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count, /* maximum distance squared for comparisons */ double max_sq_length = pow(MAX_RECIP_DISTANCE, 2); - for ( i=0; i Date: Wed, 5 Jul 2017 10:12:32 +0200 Subject: Shoved a bunch of the stuff being passed from function to function into TakeTwoCell, and shoved gsl_vector allocation into it as well to reduce alloc events --- libcrystfel/src/taketwo.c | 133 ++++++++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 69 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 4cd90cd4..c1011a96 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -92,6 +92,12 @@ struct TakeTwoCell UnitCell *cell; gsl_matrix **rotSymOps; unsigned int numOps; + struct SpotVec **obs_vecs; // Pointer to an array + int obs_vec_count; + gsl_matrix *twiz1Tmp; + gsl_matrix *twiz2Tmp; + gsl_vector *vec1Tmp; + gsl_vector *vec2Tmp; }; @@ -118,7 +124,7 @@ struct TakeTwoCell #define ANGLE_TOLERANCE (deg2rad(0.6)) /* Tolerance for rot_mats_are_similar */ -#define TRACE_TOLERANCE (deg2rad(2.5)) +#define TRACE_TOLERANCE (deg2rad(3.0)) /** TODO: * @@ -467,13 +473,11 @@ static void rotation_between_vectors(struct rvec a, struct rvec b, } -static gsl_vector *rvec_to_gsl(struct rvec v) +static void rvec_to_gsl(gsl_vector *newVec, struct rvec v) { - gsl_vector *a = gsl_vector_alloc(3); - gsl_vector_set(a, 0, v.u); - gsl_vector_set(a, 1, v.v); - gsl_vector_set(a, 2, v.w); - return a; + gsl_vector_set(newVec, 0, v.u); + gsl_vector_set(newVec, 1, v.v); + gsl_vector_set(newVec, 2, v.w); } @@ -493,11 +497,13 @@ struct rvec gsl_to_rvec(gsl_vector *a) * to 'pre-scan' vectors beforehand. */ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, struct rvec cell1, struct rvec cell2, - gsl_matrix *twiz1, gsl_matrix *twiz2) + struct TakeTwoCell *cell) { gsl_matrix *fullMat; - gsl_vector *cell2v = rvec_to_gsl(cell2); - gsl_vector *cell2vr = gsl_vector_calloc(3); + rvec_to_gsl(cell->vec1Tmp, cell2); + +// gsl_vector *cell2v = rvec_to_gsl(cell2); +// gsl_vector *cell2vr = gsl_vector_calloc(3); normalise_rvec(&obs1); normalise_rvec(&obs2); @@ -506,29 +512,26 @@ static gsl_matrix *generate_rot_mat(struct rvec obs1, struct rvec obs2, /* Rotate reciprocal space so that the first simulated vector lines up * with the observed vector. */ - rotation_between_vectors(cell1, obs1, twiz1); + rotation_between_vectors(cell1, obs1, cell->twiz1Tmp); normalise_rvec(&obs1); /* Multiply cell2 by rotateSpotDiffMatrix --> cell2vr */ - gsl_blas_dgemv(CblasNoTrans, 1.0, twiz1, cell2v, - 0.0, cell2vr); + gsl_blas_dgemv(CblasNoTrans, 1.0, cell->twiz1Tmp, cell->vec1Tmp, + 0.0, cell->vec2Tmp); /* Now we twirl around the firstAxisUnit until the rotated simulated * vector matches the second observed vector as closely as possible. */ - closest_rot_mat(gsl_to_rvec(cell2vr), obs2, obs1, twiz2); + closest_rot_mat(gsl_to_rvec(cell->vec2Tmp), obs2, obs1, cell->twiz2Tmp); /* We want to apply the first matrix and then the second matrix, * so we multiply these. */ fullMat = gsl_matrix_calloc(3, 3); gsl_blas_dgemm(CblasTrans, CblasTrans, 1.0, - twiz1, twiz2, 0.0, fullMat); + cell->twiz1Tmp, cell->twiz2Tmp, 0.0, fullMat); gsl_matrix_transpose(fullMat); - gsl_vector_free(cell2v); - gsl_vector_free(cell2vr); - return fullMat; } @@ -664,15 +667,13 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, int *obs_members, int *match_members, - int member_num) + int member_num, struct TakeTwoCell *cell) { gsl_matrix *sub = gsl_matrix_calloc(3, 3); gsl_matrix *mul = gsl_matrix_calloc(3, 3); - - gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); - gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); - gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) - member_num); + gsl_matrix **rotations = malloc(sizeof(*rotations)* pow(member_num, 2) + - member_num); int i, j, count; @@ -690,7 +691,7 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, rotations[count] = generate_rot_mat(i_obsvec, j_obsvec, i_cellvec, j_cellvec, - twiz1, twiz2); + cell); count++; } @@ -725,8 +726,6 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, free(rotations); gsl_matrix_free(sub); gsl_matrix_free(mul); - gsl_matrix_free(twiz1); - gsl_matrix_free(twiz2); return 1; } @@ -738,8 +737,6 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, { int num_occupied = 0; gsl_matrix **old_mats = calloc(*match_count, sizeof(gsl_matrix *)); - gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); - gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); if (old_mats == NULL) { @@ -760,8 +757,7 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, struct rvec j_cellvec = his_obs->matches[his_match]; gsl_matrix *mat = generate_rot_mat(i_obsvec, j_obsvec, - i_cellvec, j_cellvec, - twiz1, twiz2); + i_cellvec, j_cellvec, cell); int found = 0; @@ -799,14 +795,16 @@ static int weed_duplicate_matches(struct SpotVec *her_obs, return 1; } -static signed int find_next_index(gsl_matrix *rot, struct SpotVec *obs_vecs, - int obs_vec_count, int *obs_members, +static signed int find_next_index(gsl_matrix *rot, int *obs_members, int *match_members, int start, int member_num, int *match_found, struct TakeTwoCell *cell) { + struct SpotVec *obs_vecs = *(cell->obs_vecs); + int obs_vec_count = cell->obs_vec_count; + gsl_matrix *sub = gsl_matrix_calloc(3, 3); + gsl_matrix *mul = gsl_matrix_calloc(3, 3); + int i, j, k; - gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); - gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); for ( i=start; iobs_vecs); + int obs_vec_count = cell->obs_vec_count; + /* indices of members of the self-consistent network of vectors */ int obs_members[MAX_NETWORK_MEMBERS]; int match_members[MAX_NETWORK_MEMBERS]; @@ -927,8 +927,7 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, int match_found = -1; - signed int next_index = find_next_index(rot, obs_vecs, - obs_vec_count, obs_members, + signed int next_index = find_next_index(rot, obs_members, match_members, start, member_num, &match_found, cell); @@ -971,30 +970,29 @@ static int grow_network(gsl_matrix *rot, struct SpotVec *obs_vecs, } finish_solution(rot, obs_vecs, obs_members, - match_members, member_num); + match_members, member_num, cell); return ( member_num > NETWORK_MEMBER_THRESHOLD ); } -static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, - int j, int i_match, int j_match, gsl_matrix **rotation, - int *max_members, struct TakeTwoCell *cell) +static int start_seed(int i, int j, int i_match, int j_match, + gsl_matrix **rotation, int *max_members, + struct TakeTwoCell *cell) { + struct SpotVec *obs_vecs = *(cell->obs_vecs); + gsl_matrix *rot_mat; - gsl_matrix *twiz1 = gsl_matrix_calloc(3, 3); - gsl_matrix *twiz2 = gsl_matrix_calloc(3, 3); rot_mat = generate_rot_mat(obs_vecs[i].obsvec, obs_vecs[j].obsvec, obs_vecs[i].matches[i_match], obs_vecs[j].matches[j_match], - twiz1, twiz2); + cell); /* Try to expand this rotation matrix to a larger network */ - int success = grow_network(rot_mat, obs_vecs, obs_vec_count, - i, j, i_match, j_match, max_members, + int success = grow_network(rot_mat, i, j, i_match, j_match, max_members, cell); /* return this matrix and if it was immediately successful */ @@ -1003,9 +1001,11 @@ static int start_seed(struct SpotVec *obs_vecs, int obs_vec_count, int i, return success; } -static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, - gsl_matrix **rotation, struct TakeTwoCell *cell) +static int find_seed(gsl_matrix **rotation, struct TakeTwoCell *cell) { + struct SpotVec *obs_vecs = *(cell->obs_vecs); + int obs_vec_count = cell->obs_vec_count; + /* META: Maximum achieved maximum network membership */ int max_max_members = 0; gsl_matrix *best_rotation = NULL; @@ -1064,8 +1064,7 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, int max_members = 0; - int success = start_seed(obs_vecs, obs_vec_count, - i, j, + int success = start_seed(i, j, i_idx[k], j_idx[k], rotation, &max_members, cell); @@ -1085,21 +1084,6 @@ static int find_seed(struct SpotVec *obs_vecs, int obs_vec_count, *rotation = NULL; } } - -// unsigned long now_time = time(NULL); -// unsigned int seconds = now_time - start_time; - - // Commented out for the time being. - /* - if (seconds > 30) { - // Heading towards CrystFEL cutoff so - // return your best guess and run - free(i_idx); free(j_idx); - - *rotation = best_rotation; - return (best_rotation != NULL); - } - */ } free(i_idx); @@ -1457,6 +1441,10 @@ static void cleanup_taketwo_cell(struct TakeTwoCell *ttCell) gsl_matrix_free(ttCell->rotSymOps[i]); } + free(ttCell->vec1Tmp); + free(ttCell->vec2Tmp); + free(ttCell->twiz1Tmp); + free(ttCell->twiz2Tmp); free(ttCell->rotSymOps); } @@ -1488,6 +1476,10 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) struct TakeTwoCell ttCell; ttCell.cell = cell; ttCell.rotSymOps = NULL; + ttCell.twiz1Tmp = gsl_matrix_calloc(3, 3); + ttCell.twiz2Tmp = gsl_matrix_calloc(3, 3); + ttCell.vec1Tmp = gsl_vector_calloc(3); + ttCell.vec2Tmp = gsl_vector_calloc(3); ttCell.numOps = 0; success = generate_rotation_sym_ops(&ttCell); @@ -1499,6 +1491,9 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count); if ( !success ) return NULL; + ttCell.obs_vecs = &obs_vecs; + ttCell.obs_vec_count = obs_vec_count; + success = match_obs_to_cell_vecs(asym_vecs, asym_vec_count, obs_vecs, obs_vec_count, 1); @@ -1510,7 +1505,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) if ( !success ) return NULL; - find_seed(obs_vecs, obs_vec_count, &solution, &ttCell); + find_seed(&solution, &ttCell); if ( solution == NULL ) { cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count); -- cgit v1.2.3 From 548be7934456e116c5a8832c6e8e2f82f165c516 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 6 Jul 2017 17:15:10 +0200 Subject: Use void pointers for indexing engine private stuff --- libcrystfel/src/taketwo.c | 8 ++++---- libcrystfel/src/taketwo.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index c1011a96..434c5b0d 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1523,7 +1523,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) /* CrystFEL interface hooks */ -int taketwo_index(struct image *image, IndexingPrivate *ipriv) +int taketwo_index(struct image *image, void *priv) { Crystal *cr; UnitCell *cell; @@ -1575,8 +1575,8 @@ int taketwo_index(struct image *image, IndexingPrivate *ipriv) } -IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, - struct detector *det, float *ltl) +void *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, + struct detector *det, float *ltl) { struct taketwo_private *tp; @@ -1624,7 +1624,7 @@ IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, tp->cell = cell; tp->indm = *indm; - return (IndexingPrivate *)tp; + return tp; } diff --git a/libcrystfel/src/taketwo.h b/libcrystfel/src/taketwo.h index 35f7cbe3..4c06e334 100644 --- a/libcrystfel/src/taketwo.h +++ b/libcrystfel/src/taketwo.h @@ -33,9 +33,9 @@ #include "cell.h" -extern IndexingPrivate *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, - struct detector *det, float *ltl); -extern int taketwo_index(struct image *image, IndexingPrivate *ipriv); +extern void *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, + struct detector *det, float *ltl); +extern int taketwo_index(struct image *image, void *priv); extern void taketwo_cleanup(IndexingPrivate *pp); #endif /* TAKETWO_H */ -- cgit v1.2.3 From 48d4a6b8e82cce81222ec58fdfb488ed79ce0bcf Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 6 Jul 2017 17:05:40 +0200 Subject: Remove unnecessary headers and move an include --- libcrystfel/src/taketwo.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 434c5b0d..605ced7f 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1,15 +1,3 @@ -// -// ignore.h -// cppxfel -// -// Created by Helen Ginn on 24/03/2017. -// Copyright (c) 2017 Division of Structural Biology Oxford. All rights reserved. -// - -#ifndef cppxfel_ignore_h -#define cppxfel_ignore_h - - /* * taketwo.c * @@ -45,13 +33,13 @@ #include #include #include +#include #include "cell-utils.h" #include "index.h" #include "taketwo.h" #include "peaks.h" #include "symmetry.h" -#include /** * spotvec @@ -1634,5 +1622,3 @@ void taketwo_cleanup(IndexingPrivate *pp) free(tp); } - -#endif -- cgit v1.2.3 From 92d00d19d5b4a6b72a35183bea6a83a4062e5eca Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 6 Jul 2017 17:25:03 +0200 Subject: Fix typo --- libcrystfel/src/taketwo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 605ced7f..7ae77f4a 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1518,7 +1518,7 @@ int taketwo_index(struct image *image, void *priv) struct rvec *rlps; int n_rlps = 0; int i; - struct taketwo_private *tp = (struct taketwo_private *)ipriv; + struct taketwo_private *tp = (struct taketwo_private *)priv; rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); for ( i=0; ifeatures); i++ ) { -- cgit v1.2.3 From 5bf72b123cb582f63652e32420d4fbe748cbb8d2 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 6 Jul 2017 17:06:52 +0200 Subject: indexamajig: Add TakeTwo-specific options --- libcrystfel/src/index.c | 9 +++++++-- libcrystfel/src/index.h | 5 ++++- libcrystfel/src/taketwo.c | 2 +- libcrystfel/src/taketwo.h | 22 ++++++++++++++------ src/indexamajig.c | 51 +++++++++++++++++++++++++++++++++++++++++++++-- src/process_image.h | 2 ++ 6 files changed, 79 insertions(+), 12 deletions(-) diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index bdabb062..b00f13aa 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -64,6 +64,8 @@ struct _indexingprivate UnitCell *target_cell; float tolerance[4]; + struct taketwo_options *ttopts; + int n_methods; IndexingMethod *methods; void **engine_private; @@ -157,7 +159,8 @@ static void *prepare_method(IndexingMethod *m, UnitCell *cell, IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell, struct detector *det, float *ltl, - int no_refine, const char *options) + int no_refine, const char *options, + struct taketwo_options *ttopts) { int i, n; char **method_strings; @@ -216,6 +219,8 @@ IndexingPrivate *setup_indexing(const char *method_list, UnitCell *cell, } for ( i=0; i<4; i++ ) ipriv->tolerance[i] = ltl[i]; + ipriv->ttopts = ttopts; + return ipriv; } @@ -339,7 +344,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, break; case INDEXING_TAKETWO : - r = taketwo_index(image, mpriv); + r = taketwo_index(image, ipriv->ttopts, mpriv); break; default : diff --git a/libcrystfel/src/index.h b/libcrystfel/src/index.h index 2107ed80..8b3aadeb 100644 --- a/libcrystfel/src/index.h +++ b/libcrystfel/src/index.h @@ -157,10 +157,13 @@ extern IndexingMethod get_indm_from_string(const char *method); #include "detector.h" #include "cell.h" #include "image.h" +#include "taketwo.h" + extern IndexingPrivate *setup_indexing(const char *methods, UnitCell *cell, struct detector *det, float *ltl, - int no_refine, const char *options); + int no_refine, const char *options, + struct taketwo_options *ttopts); extern void index_pattern(struct image *image, IndexingPrivate *ipriv); diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 7ae77f4a..307c6737 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -1511,7 +1511,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) /* CrystFEL interface hooks */ -int taketwo_index(struct image *image, void *priv) +int taketwo_index(struct image *image, struct taketwo_options *opts, void *priv) { Crystal *cr; UnitCell *cell; diff --git a/libcrystfel/src/taketwo.h b/libcrystfel/src/taketwo.h index 4c06e334..a03292a8 100644 --- a/libcrystfel/src/taketwo.h +++ b/libcrystfel/src/taketwo.h @@ -3,13 +3,13 @@ * * Rewrite of TakeTwo algorithm (Acta D72 (8) 956-965) for CrystFEL * - * Copyright © 2016 Helen Ginn - * Copyright © 2016 Deutsches Elektronen-Synchrotron DESY, - * a research centre of the Helmholtz Association. + * Copyright © 2016-2017 Helen Ginn + * Copyright © 2016-2017 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. * * Authors: - * 2016 Helen Ginn - * 2016 Thomas White + * 2016 Helen Ginn + * 2016-2017 Thomas White * * This file is part of CrystFEL. * @@ -32,10 +32,20 @@ #define TAKETWO_H #include "cell.h" +#include "index.h" + +struct taketwo_options +{ + int member_thresh; + double len_tol; + double angle_tol; + double trace_tol; +}; + extern void *taketwo_prepare(IndexingMethod *indm, UnitCell *cell, struct detector *det, float *ltl); -extern int taketwo_index(struct image *image, void *priv); +extern int taketwo_index(struct image *image, struct taketwo_options *opts, void *priv); extern void taketwo_cleanup(IndexingPrivate *pp); #endif /* TAKETWO_H */ diff --git a/src/indexamajig.c b/src/indexamajig.c index ce87fde6..33eed81f 100644 --- a/src/indexamajig.c +++ b/src/indexamajig.c @@ -62,7 +62,7 @@ #include "reflist-utils.h" #include "cell-utils.h" #include "integration.h" - +#include "taketwo.h" #include "im-sandbox.h" @@ -171,6 +171,11 @@ static void show_help(const char *s) " Given as a list of comma separated list of \n" " indexer specific, key word arguments.\n" " Example: \"arg1=10,arg2=500\" \n" +"\nLow-level options for the TakeTwo indexer:\n\n" +" --taketwo-member-threshold Minimum number of members in network\n" +" --taketwo-len-tolerance Reciprocal space length tolerance (1/A)\n" +" --taketwo-angle-tolerance Reciprocal space angle tolerance (in degrees)\n" +" --taketwo-trace-tolerance Rotation matrix trace tolerance\n" ); } @@ -276,6 +281,10 @@ int main(int argc, char *argv[]) iargs.fix_divergence = -1.0; iargs.felix_options = NULL; iargs.profile = 0; + iargs.taketwo_opts.member_thresh = -1; + iargs.taketwo_opts.len_tol = -1.0; + iargs.taketwo_opts.angle_tol = -1.0; + iargs.taketwo_opts.trace_tol = -1.0; /* Long options */ const struct option longopts[] = { @@ -344,6 +353,10 @@ int main(int argc, char *argv[]) {"min-res", 1, NULL, 29}, {"max-res", 1, NULL, 30}, {"min-peaks", 1, NULL, 31}, + {"taketwo-member-thresh", 1, NULL, 32}, + {"taketwo-len-tol", 1, NULL, 33}, + {"taketwo-angle-tol", 1, NULL, 34}, + {"taketwo-trace-tol", 1, NULL, 35}, {0, 0, NULL, 0} }; @@ -551,6 +564,39 @@ int main(int argc, char *argv[]) iargs.min_peaks = atoi(optarg); break; + case 32: + if ( sscanf(optarg, "%i", &iargs.taketwo_opts.member_thresh) != 1 ) + { + ERROR("Invalid value for --taketwo-member-threshold\n"); + return 1; + } + break; + + case 33: + if ( sscanf(optarg, "%lf", &iargs.taketwo_opts.len_tol) != 1 ) + { + ERROR("Invalid value for --taketwo-len-tolerance\n"); + return 1; + } + break; + + case 34: + if ( sscanf(optarg, "%lf", &iargs.taketwo_opts.angle_tol) != 1 ) + { + ERROR("Invalid value for --taketwo-angle-tolerance\n"); + return 1; + } + break; + + + case 35: + if ( sscanf(optarg, "%lf", &iargs.taketwo_opts.trace_tol) != 1 ) + { + ERROR("Invalid value for --taketwo-trace-tolerance\n"); + return 1; + } + break; + case 0 : break; @@ -803,7 +849,8 @@ int main(int argc, char *argv[]) iargs.ipriv = setup_indexing(indm_str, iargs.cell, iargs.det, iargs.tols, no_refine, - iargs.felix_options); + iargs.felix_options, + &iargs.taketwo_opts); if ( iargs.ipriv == NULL ) { ERROR("Failed to set up indexing system\n"); return 1; diff --git a/src/process_image.h b/src/process_image.h index ec51c188..3e87b922 100644 --- a/src/process_image.h +++ b/src/process_image.h @@ -39,6 +39,7 @@ struct index_args; #include "integration.h" #include "im-sandbox.h" #include "time-accounts.h" +#include "taketwo.h" enum { @@ -100,6 +101,7 @@ struct index_args float fix_divergence; char *felix_options; int profile; /* Whether or not to do wall clock profiling */ + struct taketwo_options taketwo_opts; }; -- cgit v1.2.3 From 2eda1de146f75d0116c968c9331bbf2a3d06bf89 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 7 Jul 2017 11:23:42 +0200 Subject: Documentation for TakeTwo indexamajig options --- doc/man/indexamajig.1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/man/indexamajig.1 b/doc/man/indexamajig.1 index eaf812d6..c3189f22 100644 --- a/doc/man/indexamajig.1 +++ b/doc/man/indexamajig.1 @@ -401,6 +401,14 @@ Skip the prediction refinement step. .PD Display timing data for performance monitoring. +.PD 0 +.IP \fB--taketwo-member-threshold=\fIn\fR +.IP \fB--taketwo-len-tolerance=\fIn\fR +.IP \fB--taketwo-angle-tolerance=\fIn\fR +.IP \fB--taketwo-trace-tolerance=\fIn\fR +.PD +These set low-level parameters for the TakeTwo indexing algorithm. Respectively, the minimum number of vectors in the network before the pattern is considered indexed, the length and angle tolerances (in reciprocal Angstroms and degrees, respectively) and the matrix trace tolerance for considering rotation matrices as equal. + .PD 0 .IP \fB--felix-options\fR .PD -- cgit v1.2.3 From 3ea6ecf3264ffa4541dfb121a1a684f3b0a3d4fc Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 7 Jul 2017 11:43:19 +0200 Subject: Convert angle_tol to radians --- src/indexamajig.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/indexamajig.c b/src/indexamajig.c index 33eed81f..2a7a5509 100644 --- a/src/indexamajig.c +++ b/src/indexamajig.c @@ -586,6 +586,7 @@ int main(int argc, char *argv[]) ERROR("Invalid value for --taketwo-angle-tolerance\n"); return 1; } + iargs.taketwo_opts.angle_tol = deg2rad(iargs.taketwo_opts.angle_tol); break; -- cgit v1.2.3 From bf292092e93994fc70f29758f90a74282e5b9492 Mon Sep 17 00:00:00 2001 From: cppxfel Date: Tue, 18 Jul 2017 18:22:31 +0100 Subject: Crashy for unknown reason, but have added the code for using custom params. --- libcrystfel/src/taketwo.c | 64 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 307c6737..12b608f8 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -82,6 +82,7 @@ struct TakeTwoCell unsigned int numOps; struct SpotVec **obs_vecs; // Pointer to an array int obs_vec_count; + struct taketwo_options *options; gsl_matrix *twiz1Tmp; gsl_matrix *twiz2Tmp; gsl_vector *vec1Tmp; @@ -403,7 +404,7 @@ static SymOpList *sym_ops_for_cell(UnitCell *cell) static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, gsl_matrix *sub, gsl_matrix *mul, - double *score) + double *score, struct TakeTwoCell *cell) { double tr; @@ -415,9 +416,7 @@ static int rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, tr = matrix_trace(mul); if (score != NULL) *score = tr; - double max = sqrt(4.0*(1.0-cos(TRACE_TOLERANCE))); - - return (tr < max); + return (tr < cell->options->trace_tol); } static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, @@ -435,7 +434,7 @@ static int symm_rot_mats_are_similar(gsl_matrix *rot1, gsl_matrix *rot2, gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, rot1, symOp, 0.0, testRot); - if (rot_mats_are_similar(testRot, rot2, sub, mul, NULL)) { + if (rot_mats_are_similar(testRot, rot2, sub, mul, NULL, cell)) { gsl_matrix_free(testRot); gsl_matrix_free(sub); gsl_matrix_free(mul); @@ -559,7 +558,7 @@ static int obs_shares_spot_w_array(struct SpotVec *obs_vecs, int test_idx, static int obs_vecs_match_angles(struct SpotVec *her_obs, struct SpotVec *his_obs, int **her_match_idxs, int **his_match_idxs, - int *match_count) + int *match_count, struct TakeTwoCell *cell) { int i, j; *match_count = 0; @@ -585,7 +584,7 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs, double angle_diff = fabs(theory_angle - obs_angle); - if ( angle_diff < ANGLE_TOLERANCE ) { + if ( angle_diff < cell->options->angle_tol ) { // in the case of a brief check only if (!her_match_idxs || !his_match_idxs) { return 1; @@ -694,7 +693,7 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs, double addition; rot_mats_are_similar(rotations[i], rotations[j], sub, mul, - &addition); + &addition, cell); current_score += addition; } @@ -839,7 +838,7 @@ static signed int find_next_index(gsl_matrix *rot, int *obs_members, double trace = 0; int ok = rot_mats_are_similar(rot, test_rot, - sub, mul, &trace); + sub, mul, &trace, cell); gsl_matrix_free(test_rot); @@ -954,13 +953,13 @@ static int grow_network(gsl_matrix *rot, int obs_idx1, int obs_idx2, } /* If member_num is high enough, we want to return a yes */ - if ( member_num > NETWORK_MEMBER_THRESHOLD ) break; + if ( member_num > cell->options->member_thresh ) break; } finish_solution(rot, obs_vecs, obs_members, match_members, member_num, cell); - return ( member_num > NETWORK_MEMBER_THRESHOLD ); + return ( member_num > cell->options->member_thresh ); } @@ -1016,19 +1015,16 @@ static int find_seed(gsl_matrix **rotation, struct TakeTwoCell *cell) if ( !shared ) continue; - /* cell vector index matches stored in i, j and total number - * stored in int matches. + /* cell vector index matches stored in i, j and total + * number stored in int matches. */ int *i_idx = 0; int *j_idx = 0; int matches; - // double dist1Pc = 100 * obs_vecs[i].distance / MAX_RECIP_DISTANCE; -// double dist2Pc = 100 * obs_vecs[j].distance / MAX_RECIP_DISTANCE; - /* Check to see if any angles match from the cell vectors */ obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j], - &i_idx, &j_idx, &matches); + &i_idx, &j_idx, &matches, cell); if ( matches == 0 ) { free(i_idx); free(j_idx); @@ -1192,7 +1188,7 @@ static int sort_func(const void *av, const void *bv) static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, struct SpotVec *obs_vecs, int obs_vec_count, - int is_asymmetric) + int is_asymmetric, struct TakeTwoCell *cell) { int i, j; @@ -1209,7 +1205,7 @@ static int match_obs_to_cell_vecs(struct rvec *cell_vecs, int cell_vec_count, /* check if this matches the observed length */ double dist_diff = fabs(cell_length - obs_length); - if ( dist_diff > RECIP_TOLERANCE ) continue; + if ( dist_diff > cell->options->len_tol ) continue; /* we have a match, add to array! */ @@ -1449,7 +1445,8 @@ static void cleanup_taketwo_cell(struct TakeTwoCell *ttCell) * @rot: pointer to be given an assignment (hopefully) if indexing is * successful. **/ -static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) +static UnitCell *run_taketwo(UnitCell *cell, struct taketwo_options *opts, + struct rvec *rlps, int rlp_count) { int cell_vec_count = 0; int asym_vec_count = 0; @@ -1463,6 +1460,7 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) struct TakeTwoCell ttCell; ttCell.cell = cell; + ttCell.options = opts; ttCell.rotSymOps = NULL; ttCell.twiz1Tmp = gsl_matrix_calloc(3, 3); ttCell.twiz2Tmp = gsl_matrix_calloc(3, 3); @@ -1483,10 +1481,10 @@ static UnitCell *run_taketwo(UnitCell *cell, struct rvec *rlps, int rlp_count) ttCell.obs_vec_count = obs_vec_count; success = match_obs_to_cell_vecs(asym_vecs, asym_vec_count, - obs_vecs, obs_vec_count, 1); + obs_vecs, obs_vec_count, 1, &ttCell); success = match_obs_to_cell_vecs(cell_vecs, cell_vec_count, - obs_vecs, obs_vec_count, 0); + obs_vecs, obs_vec_count, 0, &ttCell); free(cell_vecs); free(asym_vecs); @@ -1520,6 +1518,26 @@ int taketwo_index(struct image *image, struct taketwo_options *opts, void *priv) int i; struct taketwo_private *tp = (struct taketwo_private *)priv; + /* Replace negative values in options with defaults */ + + if (opts->member_thresh < 0) { + opts->member_thresh = NETWORK_MEMBER_THRESHOLD; + } + + if (opts->len_tol < 0) { + opts->len_tol = RECIP_TOLERANCE; + } + + if (opts->angle_tol < 0) { + opts->angle_tol = ANGLE_TOLERANCE; + } + + if (opts->trace_tol < 0) { + opts->trace_tol = TRACE_TOLERANCE; + } + + opts->trace_tol = sqrt(4.0*(1.0-cos(opts->trace_tol))); + rlps = malloc((image_feature_count(image->features)+1)*sizeof(struct rvec)); for ( i=0; ifeatures); i++ ) { struct imagefeature *pk = image_get_feature(image->features, i); @@ -1533,7 +1551,7 @@ int taketwo_index(struct image *image, struct taketwo_options *opts, void *priv) rlps[n_rlps].v = 0.0; rlps[n_rlps++].w = 0.0; - cell = run_taketwo(tp->cell, rlps, n_rlps); + cell = run_taketwo(tp->cell, opts, rlps, n_rlps); free(rlps); if ( cell == NULL ) return 0; -- cgit v1.2.3 From ffca045ff453e41a0aed290e89c24324ddd97bec Mon Sep 17 00:00:00 2001 From: Thomas White Date: Thu, 20 Jul 2017 17:29:34 +0200 Subject: Change units for TakeTwo parameters --- libcrystfel/src/taketwo.c | 6 +----- src/indexamajig.c | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c index 12b608f8..ecd2c447 100644 --- a/libcrystfel/src/taketwo.c +++ b/libcrystfel/src/taketwo.c @@ -115,11 +115,7 @@ struct TakeTwoCell /* Tolerance for rot_mats_are_similar */ #define TRACE_TOLERANCE (deg2rad(3.0)) -/** TODO: - * - * - May need to be capable of playing with the tolerances/#defined stuff. - * - Multiple lattices - */ +/* TODO: Multiple lattices */ /* ------------------------------------------------------------------------ diff --git a/src/indexamajig.c b/src/indexamajig.c index 2a7a5509..d232b66f 100644 --- a/src/indexamajig.c +++ b/src/indexamajig.c @@ -175,7 +175,7 @@ static void show_help(const char *s) " --taketwo-member-threshold Minimum number of members in network\n" " --taketwo-len-tolerance Reciprocal space length tolerance (1/A)\n" " --taketwo-angle-tolerance Reciprocal space angle tolerance (in degrees)\n" -" --taketwo-trace-tolerance Rotation matrix trace tolerance\n" +" --taketwo-trace-tolerance Rotation matrix equivalence tolerance (in degrees)\n" ); } @@ -578,6 +578,7 @@ int main(int argc, char *argv[]) ERROR("Invalid value for --taketwo-len-tolerance\n"); return 1; } + iargs.taketwo_opts.len_tol *= 1e10; break; case 34: @@ -596,6 +597,7 @@ int main(int argc, char *argv[]) ERROR("Invalid value for --taketwo-trace-tolerance\n"); return 1; } + iargs.taketwo_opts.trace_tol = deg2rad(iargs.taketwo_opts.trace_tol); break; case 0 : -- cgit v1.2.3