/* check that the two are not mirror images - count on it being a triple*/ int hand (Representation * X_rep, int *set_of_directions_x) { double **x = X_rep->full; double **x_cm = X_rep->cm; double cm_vector[3], avg_cm[3], cross[3], d, aux; int i, ray_a, ray_b, ray_c, a, b, c; a = 0; b = 1; c = 2; /*****************************/ /*****************************/ ray_a = set_of_directions_x[a]; ray_b = set_of_directions_x[b]; ray_c = set_of_directions_x[c]; /* I better not use the cross prod here: a small diff int he angle makeing them pointing toward each other or away from each other changes the direction of cross prod; rather, use one vector, and distance between the cm's as the other */ for (i=0; i<3; i++ ) { cm_vector[i] = x_cm[ray_b][i] - x_cm[ray_a][i]; } normalized_cross (x[ray_a], x[ray_b], cross, &aux); /* note I am making another cm vector here */ for (i=0; i<3; i++ ) { avg_cm[i] = (x_cm[ray_b][i] + x_cm[ray_a][i])/2; cm_vector[i] = x_cm[ray_c][i] - avg_cm[i]; } unnorm_dot (cm_vector, cross, &d); if ( d > 0 ) { return 0; } else { return 1; } }
int cull_by_dna (Representation * X_rep, int *set_of_directions_x, Representation * Y_rep, int *set_of_directions_y, int set_size, Map *map, double cutoff_rmsd) { double **x = X_rep->full; double **x_cm = X_rep->cm; double **y = Y_rep->full; double **y_cm = Y_rep->cm; double cm_vector[3], cross[3], distance_x, distance_y; double aux, rmsd; int NX=X_rep->N_full; int i, j, ray_a, ray_b, a; int in_triple, coord_ctr, norm; if (set_size < 1 ) return 1; for (i=0; i<NX; i++) { j = map->x2y[i]; if ( j<0) continue; /* check that i is not in the triple here */ in_triple = 0; for (a=0; a<set_size; a++) { if ( i==set_of_directions_x[a]) { in_triple =1; break; } } if (in_triple) continue; rmsd = 0.0; norm = 0; /* the rmsd for the dna of this element to the triple */ for (a=0; a<set_size; a++) { /**************************************/ ray_a = set_of_directions_x[a]; ray_b = i; /* distance of nearest approach of ray b to the cm of a, in the set of directions x */ for (coord_ctr=0; coord_ctr<3; coord_ctr++ ) { cm_vector[coord_ctr] = x_cm[ray_b][coord_ctr] - x_cm[ray_a][coord_ctr]; } normalized_cross (cm_vector, x[ray_a], cross, &distance_x); ray_a = set_of_directions_y[a]; ray_b = j; /* distance of nearest approach of ray b to the cm of a, in the set of directions y */ for (coord_ctr=0; coord_ctr<3; coord_ctr++ ) { cm_vector[coord_ctr] = y_cm[ray_b][coord_ctr] - y_cm[ray_a][coord_ctr]; } normalized_cross (cm_vector, y[ray_a], cross, &distance_y); aux = distance_x-distance_y; rmsd += aux*aux; norm ++; /**************************************/ ray_b = set_of_directions_x[a]; ray_a = i; /* distance of nearest approach of ray b to the cm of a, in the set of directions x */ for (coord_ctr=0; coord_ctr<3; coord_ctr++ ) { cm_vector[coord_ctr] = x_cm[ray_b][coord_ctr] - x_cm[ray_a][coord_ctr]; } normalized_cross (cm_vector, x[ray_a], cross, &distance_x); ray_b = set_of_directions_y[a]; ray_a = j; /* distance of nearest approach of ray b to the cm of a, in the set of directions y */ for (coord_ctr=0; coord_ctr<3; coord_ctr++ ) { cm_vector[coord_ctr] = y_cm[ray_b][coord_ctr] - y_cm[ray_a][coord_ctr]; } normalized_cross (cm_vector, y[ray_a], cross, &distance_y); aux = distance_x-distance_y; rmsd += aux*aux; norm ++; } rmsd /= norm; rmsd = sqrt(rmsd); /* if rmsd is bigger than the cutoff, lose this from the mapping */ if ( rmsd > cutoff_rmsd) { map->x2y[i] = -1; map->y2x[j] = -1; } } return 0; }
/* check that the two are not mirror images - count on it being a triple*/ int same_hand_triple (Representation * X_rep, int *set_of_directions_x, Representation * Y_rep, int *set_of_directions_y, int set_size) { double **x = X_rep->full; double **x_cm = X_rep->cm; double **y = Y_rep->full; double **y_cm = Y_rep->cm; double cm_vector[3], avg_cm[3], cross[3], dx, dy, aux; int i, ray_a, ray_b, ray_c, a, b, c; if (set_size !=3 ) return 0; a = 0; b = 1; c = 2; /*****************************/ /*****************************/ ray_a = set_of_directions_x[a]; ray_b = set_of_directions_x[b]; ray_c = set_of_directions_x[c]; /* I better not use the cross prod here: a small diff int he angle makeing them pointing toward each other or away from each other changes the direction of cross prod; rather, use one vector, and distance between the cm's as the other */ for (i=0; i<3; i++ ) { cm_vector[i] = x_cm[ray_b][i] - x_cm[ray_a][i]; } /* note that the cross product here is between the direction vector of SSE labeled a, and the vector spanning the geeometric centers of a and b - this cross prod can be undefined only if the two are stacked */ if ( ! normalized_cross (x[ray_a], cm_vector, cross, &aux)) { /* the function returns 0 on success, i.e. retval==0 means the cross product can be calculated ok. */ /* note I am making another cm vector here */ for (i=0; i<3; i++ ) { avg_cm[i] = (x_cm[ray_b][i] + x_cm[ray_a][i])/2; cm_vector[i] = x_cm[ray_c][i] - avg_cm[i]; } unnorm_dot (cm_vector, cross, &dx); /*****************************/ /*****************************/ ray_a = set_of_directions_y[a]; ray_b = set_of_directions_y[b]; ray_c = set_of_directions_y[c]; for (i=0; i<3; i++ ) { cm_vector[i] = y_cm[ray_b][i] - y_cm[ray_a][i]; } if (normalized_cross (y[ray_a], cm_vector, cross, &aux)) { /* if I can calculate the cross product for one triplet but not for the other, I declare it a different hand (this will be dropped from further consideration) */ return 0; } /* note I am making another cm vector here */ for (i=0; i<3; i++ ) { avg_cm[i] = (y_cm[ray_b][i] + y_cm[ray_a][i])/2; cm_vector[i] = y_cm[ray_c][i] - avg_cm[i]; } /*note: unnorm_dot thinks it is getting unit vectors, and evrything that is >1 will be "rounded" to 1 (similarly for -1) - it doesn't do the normalization itself*/ unnorm_dot (cm_vector, cross, &dy); if ( dx*dy < 0 ) { return 0; } else { return 1; /* this isn't err value - the handedness is the same */ } } else { /* if the vectors linking cms are parallel, the hand is the same (my defintion) */ double cm_vector_2[3], dot; ray_a = set_of_directions_y[a]; ray_b = set_of_directions_y[b]; ray_c = set_of_directions_y[c]; for (i=0; i<3; i++ ) { cm_vector_2[i] = y_cm[ray_b][i] - y_cm[ray_a][i]; } unnorm_dot(cm_vector, cm_vector_2, &dot); if ( dot > 0) { return 1; } else { return 0; } /* (hey, at least I am checking the retvals of my functions) */ } return 0; /* better safe than sorry */ }
int distance_of_nearest_approach ( Representation * X_rep, int *set_of_directions_x, Representation * Y_rep, int *set_of_directions_y, int set_size, double * rmsd_ptr) { double **x = X_rep->full; double **x_cm = X_rep->cm; double **y = Y_rep->full; double **y_cm = Y_rep->cm; double cm_vector[3], cross[3], distance_x, distance_y; double aux, rmsd; int i, ray_a, ray_b, a, b, prev_next, norm; if (set_size <=1 ) return 1; rmsd = 0.0; norm = 0; /* the rmsd for the remaining vectors is ... */ for (a=0; a<set_size; a++) { for ( prev_next = -1; prev_next <= +1; prev_next +=2 ) { b = (set_size+a+prev_next)%set_size; ray_a = set_of_directions_x[a]; ray_b = set_of_directions_x[b]; /* distance of nearest approach of ray a to the cm of b, in the set of directions x */ for (i=0; i<3; i++ ) { cm_vector[i] = x_cm[ray_b][i] - x_cm[ray_a][i]; } /* the norm of the cross product is ||cm_vector||*sin(alpha), bc the norm of the rep vectors is 1 */ normalized_cross (cm_vector, x[ray_a], cross, &distance_x); ray_a = set_of_directions_y[a]; ray_b = set_of_directions_y[b]; /* distance of nearest approach of ray a to the cm of b, in the set of directions y */ for (i=0; i<3; i++ ) { cm_vector[i] = y_cm[ray_b][i] - y_cm[ray_a][i]; } normalized_cross (cm_vector, y[ray_a], cross, &distance_y); aux = distance_x-distance_y; rmsd += aux*aux; norm ++; # if 0 printf ("%d, %d x: %2d %2d y: %2d %2d \n", a, b, set_of_directions_x[a], set_of_directions_x[b], set_of_directions_y[a], set_of_directions_y[b]); printf (" distance x: %8.3lf distance y: %8.3lf difference: %8.3lf \n", distance_x, distance_y, fabs (distance_x-distance_y)); # endif } } rmsd /= norm; rmsd = sqrt(rmsd); //printf ("***** rmsd: %8.3lf \n\n", rmsd); *rmsd_ptr = rmsd; return 0; }
/* check that the two are not mirror images - count on it being a triple*/ int same_hand_triple (Representation * X_rep, int *set_of_directions_x, Representation * Y_rep, int *set_of_directions_y, int set_size) { double **x = X_rep->full; double **x_cm = X_rep->cm; double **y = Y_rep->full; double **y_cm = Y_rep->cm; double cm_vector[3], avg_cm[3], cross[3], dx, dy, aux; int i, ray_a, ray_b, ray_c, a, b, c; if (set_size !=3 ) return 0; a = 0; b = 1; c = 2; /*****************************/ /*****************************/ ray_a = set_of_directions_x[a]; ray_b = set_of_directions_x[b]; ray_c = set_of_directions_x[c]; /* I better not use the cross prod here: a small diff int he angle makeing them pointing toward each other or away from each other changes the direction of cross prod; rather, use one vector, and distance between the cm's as the other */ for (i=0; i<3; i++ ) { cm_vector[i] = x_cm[ray_b][i] - x_cm[ray_a][i]; } normalized_cross (x[ray_a], x[ray_b], cross, &aux); /* note I am makning another cm vector here */ for (i=0; i<3; i++ ) { avg_cm[i] = (x_cm[ray_b][i] + x_cm[ray_a][i])/2; cm_vector[i] = x_cm[ray_c][i] - avg_cm[i]; } unnorm_dot (cm_vector, cross, &dx); /*****************************/ /*****************************/ ray_a = set_of_directions_y[a]; ray_b = set_of_directions_y[b]; ray_c = set_of_directions_y[c]; for (i=0; i<3; i++ ) { cm_vector[i] = y_cm[ray_b][i] - y_cm[ray_a][i]; } normalized_cross (y[ray_a], y[ray_b], cross, &aux); /* note I am makning another cm vector here */ for (i=0; i<3; i++ ) { avg_cm[i] = (y_cm[ray_b][i] + y_cm[ray_a][i])/2; cm_vector[i] = y_cm[ray_c][i] - avg_cm[i]; } /*note: unnorm_dot thinks it is getting unit vectors, and evrything that is >1 will be "rounded" to 1 (similarly for -1) - it doesn't do the normalization itself*/ unnorm_dot (cm_vector, cross, &dy); if ( dx*dy < 0 ) return 0; return 1; /* this isn't err value - the handedness is the same */ }
int qmap (double *x0, double *x1, double *y0, double *y1, double * quat){ double q1[4], q2[4]; double v[3], v2[3], cosine = 0, theta =0, sine; double x_prime[3]; int i,j; int normalized_cross (double *x, double *y, double * v, double *norm_ptr); int unnorm_dot (double *x, double *y, double * dot); /* 1) find any quat for x0 --> y0 */ /* check that it is not the same vector already: */ unnorm_dot (x0, y0, &cosine); if ( 1-cosine > 0.001 ) { double ** R; if ( normalized_cross (x0, y0, v, NULL) )return 1; theta = acos (cosine); q1[0] = cos (theta/2); sine = sin(theta/2); for (i=0; i<3; i++ ) { q1[i+1] = sine*v[i]; } if ( ! (R=dmatrix(3,3) ) ) return 1; /* compiler is bugging me otherwise */ quat_to_R (q1, R); for (i=0; i<3; i++ ) { x_prime[i] = 0; for (j=0; j<3; j++ ) { x_prime[i] += R[i][j]*x1[j]; } } free_dmatrix (R); } else { memcpy (x_prime, x1, 3*sizeof(double) ); memset (q1, 0, 4*sizeof(double) ); q1[0] = 1.0; } /* 2) find quat thru y0 which maps x' to the plane <y0,y1> */ unnorm_dot (x_prime, y1, &cosine); /* determining theta: angle btw planes = angle btw the normals */ if ( 1-cosine > 0.001 ) { if ( normalized_cross (x_prime, y0,v, NULL)) return 1; if ( normalized_cross (y1, y0, v2, NULL)) return 1; unnorm_dot (v, v2, &cosine); theta = acos (cosine); /*still need to determine the sign of rotation */ if (normalized_cross (x_prime, y1,v, NULL)) return 1; unnorm_dot (v, y0, &cosine); if ( cosine > 0.0 ) { sine = sin(theta/2); } else { sine = -sin(theta/2); } for (i=0; i<3; i++ ) { v[i] = y0[i]; } q2[0] = cos (theta/2); for (i=0; i<3; i++ ) { q2[i+1] = sine*v[i]; } } else { memset (q2, 0, 4*sizeof(double) ); q2[0] = 1.0; } /* multiply the two quats */ multiply (q2, q1, 0, quat); return 0; }
int qmap_bisec (double *x0, double *x1, double *y0, double *y1, double * quat){ double q1[4], q2[4]; double v[3], cosine = 0, theta =0, sine; double bisec_x[3], bisec_y[3]; double norm_x[3], norm_y[3]; double bisec_x_prime[3]; double norm; int i,j; int normalized_cross (double *x, double *y, double * v, double *norm_ptr); int unnorm_dot (double *x, double *y, double * dot); /* 0) find normals and bisectors */ if ( normalized_cross (x0, x1, norm_x, NULL) )return 1; if ( normalized_cross (y0, y1, norm_y, NULL) )return 1; norm = 0; for (i=0; i<3; i++ ) { bisec_x[i] = (x0[i] + x1[i])/2; norm += bisec_x[i]*bisec_x[i]; } norm += sqrt(norm); if (norm) for (i=0; i<3; i++ ) bisec_x[i] /= norm; norm = 0; for (i=0; i<3; i++ ) { bisec_y[i] = (y0[i] + y1[i])/2; norm += bisec_y[i]*bisec_y[i]; } norm += sqrt(norm); if (norm) for (i=0; i<3; i++ ) bisec_y[i] /= norm; /* 1) find any quat that will match the normals */ /* check that it is not the same vector already: */ unnorm_dot (norm_x, norm_y, &cosine); if ( 1-cosine > 0.001 ) { double ** R; if ( normalized_cross (norm_x, norm_y, v, NULL) )return 1; theta = acos (cosine); q1[0] = cos (theta/2); sine = sin(theta/2); for (i=0; i<3; i++ ) { q1[i+1] = sine*v[i]; } if ( ! (R=dmatrix(3,3) ) ) return 1; /* compiler is bugging me otherwise */ quat_to_R (q1, R); for (i=0; i<3; i++ ) { bisec_x_prime[i] = 0; for (j=0; j<3; j++ ) { bisec_x_prime[i] += R[i][j]*bisec_x[j]; } } free_dmatrix (R); } else { memcpy (bisec_x_prime, bisec_x, 3*sizeof(double)); memset (q1, 0, 4*sizeof(double) ); q1[0] = 1.0; } /* 2) find quat thru norm_y which maps bisectors one onto another */ unnorm_dot (bisec_x_prime, bisec_y, &cosine); /* determining theta: angle btw planes = angle btw the normals */ if ( 1-cosine > 0.001 ) { theta = acos (cosine); /*still need to determine the sign of rotation */ if (normalized_cross (bisec_x_prime, bisec_y, v, NULL)) return 1; unnorm_dot (v, norm_y, &cosine); if ( cosine > 0.0 ) { sine = sin(theta/2); } else { sine = -sin(theta/2); } for (i=0; i<3; i++ ) { v[i] = norm_y[i]; } q2[0] = cos (theta/2); for (i=0; i<3; i++ ) { q2[i+1] = sine*v[i]; } } else { memset (q2, 0, 4*sizeof(double) ); q2[0] = 1.0; } /* multiply the two quats */ multiply (q2, q1, 0, quat); return 0; }
/* we'll need neighbrohoods as a measure of similarity between elements */ int find_neighborhoods (Representation *rep, Representation ** hood) { double **x = rep->full; double **x_cm = rep->cm; double d, hood_radius = 10; double cm_vector[3], cross[3], csq, component; int NX = rep->N_full; int max_hood_size = NX - 1; int a, b, i; int index_a, index_b; for (a=0; a<NX; a++) hood[a]->N_full = 0; // just in case for (a=0; a<NX; a++) { for (b=a+1; b<NX; b++) { csq = 0; for (i=0; i<3; i++ ) { /* from b to a */ component = x_cm[a][i] - x_cm[b][i]; cm_vector[i] = component; csq += component*component; } /* how far is it? use distance of nearest approach; if too far, move on */ /* distance from a to the nearest point in b */ normalized_cross (cm_vector, x[b], cross, &d); if (d < hood_radius) { index_a = hood[a]->N_full; /* what is the direction to this nearest point? */ /* dir = -cm - b*sqrt(csq-d*d) */ double dist_from_cm_b = sqrt(csq-d*d); for (i=0; i<3; i++ ) { hood[a]->full [index_a] [i] = -cm_vector[i] -x[b][i]*dist_from_cm_b ; } hood[a]->N_full ++; /* type */ hood[a]->full_type[index_a] = rep->full_type[b]; } /* distance from b to the nearest point in a */ normalized_cross (cm_vector, x[a], cross, &d); if (d < hood_radius) { // d is now different number then above index_b = hood[b]->N_full; /* what is the direction to this nearest point? */ /* dir = -cm - a*sqrt(csq-d*d) */ double dist_from_cm_a = sqrt(csq-d*d); for (i=0; i<3; i++ ) { // note the oopsite dir for the cm vector hood[b]->full [index_b] [i] = cm_vector[i] -x[a][i]*dist_from_cm_a ; } hood[b]->N_full ++; /* type */ hood[a]->full_type[index_b] = rep->full_type[a]; } } } /* rotate to the frame in which the sse vector is pointing up (0,0,1) */ double rotation_axis[3], z_direction[3] = {0, 0, 1}, theta, cosine, sine; double quat[4], **R; double **rotated_hood; if ( ! (R=dmatrix(3,3) )) return 1; /* compiler is bugging me otherwise */ if ( ! (rotated_hood = dmatrix(max_hood_size,3) )) return 1; for (a=0; a<NX; a++) { unnorm_dot (x[a], z_direction, &cosine); if ( 1 - cosine <= 0.0001) { // x[a] already pretty much is z-direction // do nothing: hood is already rotated } else { normalized_cross (x[a], z_direction, rotation_axis, &d); // quaternion theta = acos (cosine); quat[0] = cos (theta/2); sine = sin(theta/2); for (i=0; i<3; i++ ) { quat[i+1] = sine*rotation_axis[i]; } // rotation quat_to_R (quat, R); // rotate all hood vectors rotate(rotated_hood, hood[a]->N_full, R, hood[a]->full ); //copy rotated hood into the old one memcpy (hood[a]->full[0], rotated_hood[0], hood[a]->N_full*3*sizeof(double)); } } free_dmatrix (R); free_dmatrix (rotated_hood); return 0; }