int mappedCoords2rotation (double **x, double **y, int no_vectors, double q[4], double **R, double T[3], double *rmsd) { double x_mp[3], y_mp[3]; int ctr; int i, j; double ATA [4][4] = {{0.0}}; double prev_ATA[4][4] = {{0.0}}; double ATA_sum [4][4] = {{0.0}}; double a[3] = {0.0}, b[3] = {0.0}; int add_matrices (double matrix1[4][4],double matrix2[4][4], double result[4][4]); int construct_ATA (double ATA[4][4], double a[3], double b[3]); /* note how we pass the matrix: pointer to the first element in the block */ void dsyev_ (char * jobz, char *uplo, int *n, double *A, int * lda, double * w, double * work, int * lwork, int *info); if (!no_vectors) { *rmsd = -1; return 1; } memset ( &(q[0]), 0, 4*sizeof(double) ); /* turn the matching atoms into vectors x and y - use only c-alphas*/ /* check: */ if (0) { printf (" Number of vectors read in: %d. \n", no_vectors); for ( ctr =0; ctr < no_vectors; ctr++ ) { printf ("\t x%1d %10.4lf %10.4lf %10.4lf ", ctr, x[0][ctr], x[1][ctr], x[2][ctr]); printf ("\t y%1d %10.4lf %10.4lf %10.4lf \n", ctr, y[0][ctr], y[1][ctr], y[2][ctr]); } exit (1); } /* find the meanpoints: */ for ( i =0; i < 3; i++ ) { x_mp[i] = 0.0; y_mp[i] = 0.0; } for ( ctr =0; ctr < no_vectors; ctr++ ) { for ( i =0; i < 3; i++ ) { x_mp[i] += x[i][ctr]; y_mp[i] += y[i][ctr]; } } for ( i =0; i < 3; i++ ) { x_mp[i] /= no_vectors; y_mp[i] /= no_vectors; } /* subtract them from x, y */ for ( ctr =0; ctr < no_vectors; ctr++ ) { for ( i =0; i < 3; i++ ) { x[i][ctr] -= x_mp[i]; y[i][ctr] -= y_mp[i]; } } /* B = ATA_sum matrix to diagonalize in order to get the quaternion */ for ( ctr =0; ctr < no_vectors; ctr++ ) { for (i=0; i<3; i++ ) { a[i] = y[i][ctr] + x[i][ctr]; b[i] = y[i][ctr] - x[i][ctr]; } construct_ATA (ATA, a, b); add_matrices (prev_ATA, ATA, ATA_sum); memcpy (prev_ATA[0], ATA_sum[0], 4*4*sizeof(double)); } for (i=0; i<4; i++ ) { for (j=0; j<4; j++ ) { ATA_sum[i][j] /= no_vectors; } } /* diagonalize ATA_sum - the eigenvector corresponsing to the smallest lambda is the quaternion we are looking for; the eigenvalue is the rmsd*/ /* use the nomenclature from dsyev*/ char jobz= 'V'; /*Compute eigenvalues and eigenvectors.*/ char uplo= 'U'; /* Upper triangle of A (the matrix we are diagonalizing) is stored; */ int n = 4; /* order and the leading dimension of A */ int lda = 4; double ** A; int info; int lwork = 200; double w [4]; double work[200]; if ( !( A=dmatrix(4,4) ) ) exit (1); memcpy (A[0], ATA_sum[0], 4*4*sizeof(double)); /* note how we pass the matrix: */ dsyev_ ( &jobz, &uplo, &n, A[0], &lda, w, work, &lwork, &info); if ( ! info) { *rmsd = sqrt (w[0]); for (i=0; i<4; i++ ) q[i] = A[0][i]; if (0) { /* w contains the eigenvalues */ printf ("\n"); for (i=0; i<4; i++ ) printf ("%8.3lf ", w[i]); printf ("\nrmsd: %8.3lf \n", *rmsd); printf ("quat:\n"); for (i=0; i<4; i++ ) printf ("%8.3lf ", q[i]); printf ("\n"); /* printf (" opt lwork: %d\n", (int) work[0]); */ } } else { fprintf (stderr, "Error in dsyev().\n"); exit (1); } /* construct the rotation matrix R */ quat_to_R (q,R); /* T = y_mp - R x_mp */ for (i=0; i<3; i++ ) { T[i] = y_mp[i]; for (j=0; j<3; j++ ) { T[i] -= R[i][j]*x_mp[j]; } } free_dmatrix(A); return 0; }
double moment ( int moment_n, double x[][3], double y[][3], double delta) { int n_steps = 100; int phi_n_steps = 100; int i, j, n; int k, t, p; double value = 0.0; double delta_sq = delta*delta; double kappa, theta, phi; double kappa_step, theta_step, phi_step; double cosk, sink, costh, sinth; double surface_element, phi_contributn; double ATA [4][4] = {{0.0}}; double prev_ATA[4][4] = {{0.0}}; double ATA_sum [4][4] = {{0.0}}; double a[3] = {0.0}, b[3] = {0.0}; double q[4] = {0.0}; /**************/ int construct_ATA (double ATA[4][4], double a[3],double b[3]); int add_matrices (double matrix1[4][4],double matrix2[4][4],double result[4][4]); double braket (double ATA[4][4], double q[4]); /* sum of A^TA matrices */ for (n=0; n<moment_n; n++ ) { for (i=0; i<3; i++ ) { a[i] = y[n][i] + x[n][i]; b[i] = y[n][i] - x[n][i]; } construct_ATA (ATA, a, b); add_matrices (prev_ATA, ATA, ATA_sum); memcpy (prev_ATA[0], ATA_sum[0], 4*4*sizeof(double)); } if (0) { /*check */ q[0] = 1; for (i=0; i<4; i++ ) { for (j=0; j<4; j++ ) { printf ("%8.3lf ", ATA_sum[i][j]); } printf ("\n"); } printf ("\n"); double aux, sum_sq = 0.0;; for (i=0; i<4; i++ ) { aux = x[1][i]-y[1][i]; sum_sq += aux*aux; } printf ( " 00: %8.4le %8.4le %8.4le \n", ATA_sum[0][0], braket(ATA_sum, q), sum_sq); exit(1); } value = 0.0; kappa_step = M_PI/n_steps; theta_step = M_PI/n_steps; phi_step = 2*M_PI/phi_n_steps; /* for angles kappa, theta phi */ for (k=1; k<=n_steps; k++) { kappa = ( (double)k-0.5)*kappa_step; cosk = cos(kappa); sink = sin(kappa); q[0] = cosk; for (t=1; t<=n_steps; t++) { theta = ( (double)t-0.5)*theta_step; sinth = sin (theta); costh = cos (theta); q[3] = sink*costh; surface_element = sink*sink*sinth; phi_contributn = 0; for (p=1; p<=phi_n_steps; p++) { phi = ((double)p-0.5)*phi_step; q[1] = sink*sinth*cos(phi); q[2] = sink*sinth*sin(phi); phi_contributn += exp(-braket(ATA_sum, q)/delta_sq); //value += sink*sink*sinth; //printf ( "%3d %3d %3d %8.4le %8.2le -- %8.4le \n", k, t, p, //braket(ATA, q), exp(-braket(ATA, q)/delta_sq), phi_contributn); } value += phi_contributn*surface_element; } } value *= kappa_step*theta_step*phi_step; /*integration steps*/ value /= 2*M_PI*M_PI; /* the function should return the average*/ return value; }
int opt_quat ( double ** x, int NX, int *set_of_directions_x, double ** y, int NY, int *set_of_directions_y, int set_size, double * q, double * rmsd) { double * x_sub[set_size], * y_sub[set_size]; int ctr; int i, j; double ATA [4][4] = {{0.0}}; double prev_ATA[4][4] = {{0.0}}; double ATA_sum [4][4] = {{0.0}}; double a[3] = {0.0}, b[3] = {0.0}; int add_matrices (double matrix1[4][4],double matrix2[4][4], double result[4][4]); int construct_ATA (double ATA[4][4], double a[3], double b[3]); /* note how we pass the matrix: pointer to the first element in the block */ void dsyev_ (char * jobz, char *uplo, int *n, double *A, int * lda, double * w, double * work, int * lwork, int *info); if (!set_size) { *rmsd = -1; return 1; } memset ( &(q[0]), 0, 4*sizeof(double) ); /* find the subset */ ctr = 0; for ( ctr =0; ctr < set_size; ctr++ ) { x_sub[ctr] = x[set_of_directions_x[ctr]]; y_sub[ctr] = y[set_of_directions_y[ctr]]; } /* check: */ if (0) { printf (" Number of vectors to match: %d. \n", set_size); for ( ctr =0; ctr < set_size; ctr++ ) { printf ("\t x%1d %10.4lf %10.4lf %10.4lf ", ctr, x_sub[ctr][0], x_sub[ctr][1], x_sub[ctr][2]); printf ("\t y%1d %10.4lf %10.4lf %10.4lf \n", ctr, y_sub[ctr][0], y_sub[ctr][1], y_sub[ctr][2]); } exit (1); } /* B = ATA_sum matrix to diagonalize in order to get the quaternion */ for ( ctr =0; ctr < set_size; ctr++ ) { for (i=0; i<3; i++ ) { a[i] = y_sub[ctr][i] + x_sub[ctr][i]; b[i] = y_sub[ctr][i] - x_sub[ctr][i]; } construct_ATA (ATA, a, b); add_matrices (prev_ATA, ATA, ATA_sum); memcpy (prev_ATA[0], ATA_sum[0], 4*4*sizeof(double)); } for (i=0; i<4; i++ ) { for (j=0; j<4; j++ ) { ATA_sum[i][j] /= set_size; } } /* diagonalize ATA_sum - the eigenvector corresponsing to the smallest lambda is the quaternion we are looking for; the eigenvalue is the rmsd*/ /* use the nomenclature from dsyev*/ char jobz= 'V'; /*Compute eigenvalues and eigenvectors.*/ char uplo= 'U'; /* Upper triangle of A (the matrix we are diagonalizing) is stored; */ int n = 4; /* order and the leading dimension of A */ int lda = 4; double ** A; int info; int lwork = 200; double w [4]; double work[200]; if ( !( A=dmatrix(4,4) ) ) exit (1); memcpy (A[0], ATA_sum[0], 4*4*sizeof(double)); /* note how we pass the matrix: */ dsyev_ ( &jobz, &uplo, &n, A[0], &lda, w, work, &lwork, &info); if ( ! info) { *rmsd = sqrt (w[0]); for (i=0; i<4; i++ ) q[i] = A[0][i]; if (0) { /* w contains the eigenvalues */ printf ("\n"); for (i=0; i<4; i++ ) printf ("%8.3lf ", w[i]); printf ("\nrmsd: %8.3lf \n", *rmsd); printf ("quat:\n"); for (i=0; i<4; i++ ) printf ("%8.3lf ", q[i]); printf ("\n"); /* printf (" opt lwork: %d\n", (int) work[0]); */ } } else { fprintf (stderr, "Error in dsyev().\n"); exit (1); } free_dmatrix(A); return 0; }