aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcrystfel/src/taketwo.c240
1 files changed, 143 insertions, 97 deletions
diff --git a/libcrystfel/src/taketwo.c b/libcrystfel/src/taketwo.c
index 46033bf9..18f8365e 100644
--- a/libcrystfel/src/taketwo.c
+++ b/libcrystfel/src/taketwo.c
@@ -142,8 +142,8 @@ struct TheoryVec
struct Seed
{
- struct SpotVec *obs1;
- struct SpotVec *obs2;
+ int obs1;
+ int obs2;
int idx1;
int idx2;
double score;
@@ -163,9 +163,13 @@ struct TakeTwoCell
UnitCell *cell; /**< Contains unit cell dimensions */
gsl_matrix **rotSymOps;
unsigned int numOps;
+
gsl_matrix **prevSols; /**< Previous solutions to be ignored */
unsigned int numPrevs; /**< Previous solution count */
- struct SpotVec **obs_vecs;
+
+ struct SpotVec *obs_vecs;
+ struct Seed *seeds;
+ int seed_count;
int obs_vec_count;
/* Options */
@@ -643,12 +647,14 @@ 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,
+static int obs_vecs_match_angles(int her, int his,
struct Seed **seeds, int *match_count,
struct TakeTwoCell *cell)
{
- int i, j;
+ struct SpotVec *obs_vecs = cell->obs_vecs;
+ struct SpotVec *her_obs = &obs_vecs[her];
+ struct SpotVec *his_obs = &obs_vecs[his];
+
*match_count = 0;
double min_angle = deg2rad(2.5);
@@ -659,10 +665,17 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
/* calculate angle between all potential theoretical vectors */
+ int i, j;
for ( i=0; i<her_obs->match_num; i++ ) {
for ( j=0; j<his_obs->match_num; j++ ) {
double score = 0;
+ if (her_obs->matches[i].asym == 0 &&
+ his_obs->matches[j].asym == 0)
+ {
+ continue;
+ }
+
struct rvec *her_match = &her_obs->matches[i].vec;
struct rvec *his_match = &his_obs->matches[j].vec;
@@ -674,14 +687,15 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
double angle_diff = fabs(theory_angle - obs_angle);
/* within basic tolerance? */
- if ( angle_diff > cell->angle_tol ) {
+ if ( angle_diff != angle_diff ||
+ angle_diff > cell->angle_tol ) {
continue;
}
- double her_dist = rvec_length(*her_match);
- double his_dist = rvec_length(*his_match);
-
- score += (her_dist + his_dist) * angle_diff;
+ double add = angle_diff;
+ if (add == add) {
+ score += add;
+ }
/* If the angles are too close to 0
or 180, one axis ill-determined */
@@ -697,7 +711,6 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
struct rvec obs_diff = diff_vec(his_obs->obsvec,
her_obs->obsvec);
- double obs_diff_dist = rvec_length(obs_diff);
theory_angle = rvec_angle(*her_match,
theory_diff);
obs_angle = rvec_angle(her_obs->obsvec, obs_diff);
@@ -707,7 +720,10 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
continue;
}
- score += (obs_diff_dist + her_dist) * angle_diff;
+ add = angle_diff;
+ if (add == add) {
+ score += add;
+ }
theory_angle = rvec_angle(*his_match,
theory_diff);
@@ -717,7 +733,10 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
continue;
}
- score += (obs_diff_dist + his_dist) * angle_diff;
+ add = angle_diff;
+ if (add == add) {
+ score += add;
+ }
/* we add a new seed to the array */
size_t new_size = (*match_count + 1);
@@ -732,11 +751,11 @@ static int obs_vecs_match_angles(struct SpotVec *her_obs,
(*seeds) = tmp_seeds;
- (*seeds)[*match_count].obs1 = her_obs;
- (*seeds)[*match_count].obs2 = his_obs;
+ (*seeds)[*match_count].obs1 = her;
+ (*seeds)[*match_count].obs2 = his;
(*seeds)[*match_count].idx1 = i;
(*seeds)[*match_count].idx2 = j;
- (*seeds)[*match_count].score = score;
+ (*seeds)[*match_count].score = score * 1000;
(*match_count)++;
}
@@ -814,10 +833,13 @@ static signed int finish_solution(gsl_matrix *rot, struct SpotVec *obs_vecs,
return 1;
}
-gsl_matrix *rot_mat_from_indices(struct SpotVec *her_obs, struct SpotVec *his_obs,
+gsl_matrix *rot_mat_from_indices(int her, int his,
int her_match, int his_match,
struct TakeTwoCell *cell)
{
+ struct SpotVec *obs_vecs = cell->obs_vecs;
+ struct SpotVec *her_obs = &obs_vecs[her];
+ struct SpotVec *his_obs = &obs_vecs[his];
struct rvec i_obsvec = her_obs->obsvec;
struct rvec j_obsvec = his_obs->obsvec;
struct rvec i_cellvec = her_obs->matches[her_match].vec;
@@ -926,7 +948,7 @@ 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);
+ 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);
@@ -1032,7 +1054,8 @@ static int grow_network(gsl_matrix *rot, int obs_idx1, int obs_idx2,
int match_idx1, int match_idx2, int *max_members,
struct TakeTwoCell *cell)
{
- struct SpotVec *obs_vecs = *(cell->obs_vecs);
+
+ struct SpotVec *obs_vecs = cell->obs_vecs;
int obs_vec_count = cell->obs_vec_count;
int *obs_members;
int *match_members;
@@ -1098,9 +1121,6 @@ static int grow_network(gsl_matrix *rot, int obs_idx1, int obs_idx2,
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;
@@ -1136,7 +1156,8 @@ 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);
+ STATUS("Start seed\n");
+ struct SpotVec *obs_vecs = cell->obs_vecs;
gsl_matrix *rot_mat;
@@ -1157,22 +1178,26 @@ static int start_seed(int i, int j, int i_match, int j_match,
return success;
}
-static int find_seed(gsl_matrix **rotation, struct TakeTwoCell *cell)
+static int sort_seed_by_score(const void *av, const void *bv)
{
- struct SpotVec *obs_vecs = *(cell->obs_vecs);
- int obs_vec_count = cell->obs_vec_count;
+ struct Seed *a = (struct Seed *)av;
+ struct Seed *b = (struct Seed *)bv;
+ return a->score > b->score;
+}
- /* META: Maximum achieved maximum network membership */
- int max_max_members = 0;
- gsl_matrix *best_rotation = NULL;
-// unsigned long start_time = time(NULL);
+static int find_seeds(struct TakeTwoCell *cell)
+{
+ struct SpotVec *obs_vecs = cell->obs_vecs;
+ int obs_vec_count = cell->obs_vec_count;
/* loop round pairs of vectors to try and find a suitable
* seed to start building a self-consistent network of vectors
*/
int i, j;
+ STATUS("Total vectors: %i\n", obs_vec_count);
+
for ( i=0; i<obs_vec_count; i++ ) {
for ( j=0; j<i; j++ ) {
@@ -1191,7 +1216,7 @@ static int find_seed(gsl_matrix **rotation, struct TakeTwoCell *cell)
struct Seed *seeds = NULL;
/* Check to see if any angles match from the cell vectors */
- obs_vecs_match_angles(&obs_vecs[i], &obs_vecs[j],
+ obs_vecs_match_angles(i, j,
&seeds, &seed_num, cell);
if (seed_num == 0)
@@ -1201,69 +1226,84 @@ static int find_seed(gsl_matrix **rotation, struct TakeTwoCell *cell)
}
/* Weed out the duplicate seeds (from symmetric
- * reflection pairs)
- */
+ * reflection pairs) */
weed_duplicate_matches(&seeds, &seed_num, 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; k<seed_num; k++ ) {
- int seed_idx1 = seeds[k].idx1;
- int seed_idx2 = seeds[k].idx2;
+ /* Add all the new seeds to the full list */
+
+ size_t new_size = cell->seed_count + seed_num;
+ new_size *= sizeof(struct Seed);
+
+ struct Seed *tmp = realloc(cell->seeds, new_size);
- if (seed_idx1 < 0 || seed_idx2 < 0) {
+ if (tmp == NULL) {
+ apologise();
+ }
+
+ cell->seeds = tmp;
+
+ for (int i = 0; i < seed_num; i++)
+ {
+ if (seeds[i].idx1 < 0 || seeds[i].idx2 < 0)
+ {
continue;
}
- int max_members = 0;
-
- int success = start_seed(i, j,
- seed_idx1, seed_idx2,
- rotation, &max_members,
- cell);
-
- if (success) {
- free(seeds);
- gsl_matrix_free(best_rotation);
- return success;
- } else {
- if (max_members > 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;
- }
- }
+ cell->seeds[cell->seed_count] = seeds[i];
+ cell->seed_count++;
}
-
- free(seeds);
}
- } /* yes this } is meant to be here */
+ }
- *rotation = best_rotation;
+ qsort(cell->seeds, cell->seed_count, sizeof(struct Seed), sort_seed_by_score);
- if (best_rotation != NULL)
+ for (int i = 0; i < 10; i++)
{
- int num = cell->numPrevs + 1;
- gsl_matrix **tmp = malloc(sizeof(gsl_matrix *) * num);
+ struct Seed seed = cell->seeds[i];
+ STATUS("%i %i %i %i %.3f\n", seed.idx1, seed.idx2,
+ seed.obs1, seed.obs2, seed.score);
+ }
- if (tmp) {
- cell->prevSols = tmp;
- } else {
- return 0;
+ return 1;
+}
+
+static int start_seeds(gsl_matrix **rotation, struct TakeTwoCell *cell)
+{
+ struct Seed *seeds = cell->seeds;
+ int seed_num = cell->seed_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<seed_num; k++ ) {
+ int seed_idx1 = seeds[k].idx1;
+ int seed_idx2 = seeds[k].idx2;
+
+ if (seed_idx1 < 0 || seed_idx2 < 0) {
+ continue;
}
- cell->prevSols[num - 1] = best_rotation;
- cell->numPrevs = num;
+ int max_members = 0;
+
+ int seed_obs1 = seeds[k].obs1;
+ int seed_obs2 = seeds[k].obs2;
+
+ int success = start_seed(seed_obs1, seed_obs2,
+ seed_idx1, seed_idx2,
+ rotation, &max_members,
+ cell);
+
+ if (success) {
+ free(seeds);
+ return success;
+ }
}
- return (best_rotation != NULL);
+ free(seeds);
+ return 0;
}
+
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)
@@ -1362,7 +1402,7 @@ struct sortme
double dist;
};
-static int sort_func(const void *av, const void *bv)
+static int sort_theory_distances(const void *av, const void *bv)
{
struct sortme *a = (struct sortme *)av;
struct sortme *b = (struct sortme *)bv;
@@ -1371,9 +1411,10 @@ static int sort_func(const void *av, const void *bv)
static int match_obs_to_cell_vecs(struct TheoryVec *cell_vecs, int cell_vec_count,
- struct SpotVec *obs_vecs, int obs_vec_count,
struct TakeTwoCell *cell)
{
+ struct SpotVec *obs_vecs = cell->obs_vecs;
+ int obs_vec_count = cell->obs_vec_count;
int i, j;
for ( i=0; i<obs_vec_count; i++ ) {
@@ -1413,7 +1454,7 @@ static int match_obs_to_cell_vecs(struct TheoryVec *cell_vecs, int cell_vec_coun
match_count = &(obs_vecs[i].match_num);
/* Sort in order to get most agreeable matches first */
- qsort(for_sort, count, sizeof(struct sortme), sort_func);
+ qsort(for_sort, count, sizeof(struct sortme), sort_theory_distances);
*match_array = malloc(count*sizeof(struct TheoryVec));
*match_count = count;
for ( j=0; j<count; j++ ) {
@@ -1434,7 +1475,7 @@ static int compare_spot_vecs(const void *av, const void *bv)
}
static int gen_observed_vecs(struct rvec *rlps, int rlp_count,
- struct SpotVec **obs_vecs, int *obs_vec_count)
+ struct TakeTwoCell *cell)
{
int i, j;
int count = 0;
@@ -1445,7 +1486,6 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count,
for ( i=0; i<rlp_count-1 && count < MAX_OBS_VECTORS; i++ ) {
for ( j=i+1; j<rlp_count; j++ ) {
-
/* calculate difference vector between rlps */
struct rvec diff = diff_vec(rlps[i], rlps[j]);
@@ -1457,13 +1497,13 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count,
count++;
struct SpotVec *temp_obs_vecs;
- temp_obs_vecs = realloc(*obs_vecs,
+ temp_obs_vecs = realloc(cell->obs_vecs,
count*sizeof(struct SpotVec));
if ( temp_obs_vecs == NULL ) {
return 0;
} else {
- *obs_vecs = temp_obs_vecs;
+ cell->obs_vecs = temp_obs_vecs;
/* initialise all SpotVec struct members */
@@ -1475,15 +1515,16 @@ static int gen_observed_vecs(struct rvec *rlps, int rlp_count,
spot_vec.her_rlp = &rlps[i];
spot_vec.his_rlp = &rlps[j];
- (*obs_vecs)[count - 1] = spot_vec;
+ cell->obs_vecs[count - 1] = spot_vec;
}
}
}
/* Sort such that the shortest distances are searched first. */
- qsort(*obs_vecs, count, sizeof(struct SpotVec), compare_spot_vecs);
+ qsort(cell->obs_vecs, count, sizeof(struct SpotVec), compare_spot_vecs);
- *obs_vec_count = count;
+ cell->obs_vec_count = count;
+ STATUS("Generated observed vectors.\n");
return 1;
}
@@ -1586,6 +1627,9 @@ static void cleanup_taketwo_cell(struct TakeTwoCell *ttCell)
gsl_matrix_free(ttCell->rotSymOps[i]);
}
+ cleanup_taketwo_obs_vecs(ttCell->obs_vecs,
+ ttCell->obs_vec_count);
+
free(ttCell->vec1Tmp);
free(ttCell->vec2Tmp);
free(ttCell->twiz1Tmp);
@@ -1612,14 +1656,16 @@ static UnitCell *run_taketwo(UnitCell *cell, const struct taketwo_options *opts,
int cell_vec_count = 0;
struct TheoryVec *theory_vecs = NULL;
UnitCell *result;
- int obs_vec_count = 0;
- struct SpotVec *obs_vecs = NULL;
int success = 0;
gsl_matrix *solution = NULL;
+ /* Initialise TakeTwoCell */
struct TakeTwoCell ttCell;
ttCell.cell = cell;
+ ttCell.seeds = NULL;
+ ttCell.seed_count = 0;
ttCell.rotSymOps = NULL;
+ ttCell.obs_vecs = NULL;
ttCell.prevSols = NULL;
ttCell.twiz1Tmp = gsl_matrix_calloc(3, 3);
ttCell.twiz2Tmp = gsl_matrix_calloc(3, 3);
@@ -1627,18 +1673,16 @@ static UnitCell *run_taketwo(UnitCell *cell, const struct taketwo_options *opts,
ttCell.vec2Tmp = gsl_vector_calloc(3);
ttCell.numOps = 0;
ttCell.numPrevs = 0;
+ ttCell.obs_vec_count = 0;
success = generate_rotation_sym_ops(&ttCell);
success = gen_theoretical_vecs(cell, &theory_vecs, &cell_vec_count);
if ( !success ) return NULL;
- success = gen_observed_vecs(rlps, rlp_count, &obs_vecs, &obs_vec_count);
+ success = gen_observed_vecs(rlps, rlp_count, &ttCell);
if ( !success ) return NULL;
- ttCell.obs_vecs = &obs_vecs;
- ttCell.obs_vec_count = obs_vec_count;
-
if ( opts->member_thresh < 0 ) {
ttCell.member_thresh = NETWORK_MEMBER_THRESHOLD;
} else {
@@ -1664,21 +1708,23 @@ static UnitCell *run_taketwo(UnitCell *cell, const struct taketwo_options *opts,
}
success = match_obs_to_cell_vecs(theory_vecs, cell_vec_count,
- obs_vecs, obs_vec_count, &ttCell);
+ &ttCell);
free(theory_vecs);
if ( !success ) return NULL;
- find_seed(&solution, &ttCell);
+ STATUS("Find seeds\n");
+ find_seeds(&ttCell);
+ start_seeds(&solution, &ttCell);
if ( solution == NULL ) {
- cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count);
return NULL;
}
+ STATUS("Returning something.\n");
+
result = transform_cell_gsl(cell, solution);
- cleanup_taketwo_obs_vecs(obs_vecs, obs_vec_count);
gsl_matrix_free(solution);
cleanup_taketwo_cell(&ttCell);