Beispiel #1
0
int svdcmp (float **A, int m, int n, float *s, float **V)
{
	float *afort, *vfort;  /*Vector format work spaces */
	int i;
	int info=0;
#ifndef SUNPERF
	int one=1;
	float *swork;
	int ldwork;
#endif

	/*Alloc work spaces and copy from numerical recipes matrix
	form to the form sunperf wants */

	afort = (float *) calloc(m*MAX(m,n),sizeof(float));
	vfort = (float *) calloc(n*n,sizeof(float));
	if( (afort == NULL) || (vfort == NULL))
		die(0,"svdcmp could not alloc work arrays\n");
#ifdef SUNPERF
	for(i=0;i<m;++i)
		scopy(n,A[i],1,(afort+i),m);
#else
        for(i=0;i<m;++i)
                scopy_(&n,A[i],&one,(afort+i),&m);
#endif
	/* old rule:  always initialize things like this */
	for(i=0;i<n*n;++i) vfort[i] = 0.0;

#ifdef SUNPERF
	sgesvd('o','s',m,n,afort,m,s,NULL,m,vfort,n,&info);
#else
	ldwork = 12+2*n;  /* This is slightly larger than the minimum
			required for safety.  Space required is never
			large by modern standards  */
	swork = calloc(ldwork,sizeof(float));
	if(n == NULL) die(0,"Cannot alloc work space for SVD routine\n");
	sgesvd_("o","s",&m,&n,afort,&m,s,NULL,&m,vfort,&n,
		swork, &ldwork,
		&info);
	free(swork);
#endif
	if(info!=0)
	{
		if(info > 0)
                	elog_notify(0,"Convergence failure in svd routine\n");
		else
			elog_notify(0,"Illegal value for argument %d passed to sgesvd\nNo solution possible\n",
			-info);
		free(afort);
		free(vfort);
		return(info);
	}
#ifdef SUNPERF
	/* note we do return something even when convergence failed.
	Must handle negative return as junk is returned then. */
	for(i=0;i<m;++i)
		scopy(n,(afort+i),m,A[i],1);
	/* Note this copies V transpose in vfort to V in the matrix V.  
	Tricky BLAS code I know*/
	for(i=0;i<n;++i)
		scopy(n,(vfort+i*n),1,V[i],1);
#else
	for(i=0;i<m;++i)
                scopy_(&n,(afort+i),&m,A[i],&one);
        for(i=0;i<n;++i)
                scopy_(&n,(vfort+i*n),&one,V[i],&one);
#endif


	free(afort);
	free(vfort);
	return(0);
}
Beispiel #2
0
/* Kabsch alignment */
void kabsch_alignment( std::vector<float> ref, std::vector<float> tar, t_tiltdata &data, gmx_bool bVerbose)
{
    if (ref.size() != tar.size())
    {
        std::cerr << "\nError! Sizes of reference coordinate matrix and simulated structure coordinate matrices do not match!" << std::endl;
        std::exit(1);
    }
    int ncoords = ref.size();
    int natoms = ncoords/3;
    // Center the two selections
    std::vector<float> stsel1(ncoords,0), stsel2(ncoords,0), stsel2T(ncoords,0);
    std::vector<float> ref_com(3,0), tar_com(3,0);
    average_coordinate(ref, ref_com);
    average_coordinate(tar, tar_com);
    for (int i=0; i<natoms; i++)
    {
        for (int j=0; j<3; j++)
        {
            stsel1[i+j*natoms] = ref[i+j*natoms] - ref_com[j];
            stsel2[i+j*natoms] = tar[i+j*natoms] - tar_com[j];
        }
    }
    // Initial residual
    float E0 = sdot(ncoords,&stsel1[0],1,&stsel1[0],1)+sdot(ncoords,&stsel2[0],1,&stsel2[0],1) ;
    // dot(target_transpose,reference)
    std::vector<float> T1_dot_2(3*natoms,0);
    sgemm('T','N',3,natoms,natoms,1,&stsel2[0],natoms,&stsel1[0],natoms,1,&T1_dot_2[0],3);
    // SVD of the dot product
    std::vector<float> U(9,0), S(3,0), V(9,0), work(5*9,0);
    int info;
    sgesvd('A','A',3,3,&T1_dot_2[0],3,&S[0],&U[0],3,&V[0],3,&work[0],9*5,info);
    /*std::cout << "\n S: ";
    for (int i=0;i<3;i++)
    {
        std::cout << S[i] << " ";
    }
    std::cout << "\n U: ";
    for (int i=0;i<9;i++)
    {
        std::cout << U[i] << " ";
    }*/
    float reflect = det3x3(&U[0]) * det3x3(&V[0]);
    if ( 1 - reflect > 1e-5)
    {
        S[2] = -S[2];
        U[6] = -U[6];
        U[7] = -U[7];
        U[8] = -U[8];
    }
    float rmsd = sqrt(fabs(
                           E0
                           - (2.0 *
                              (S[0]+S[1]+S[2])
                              )
                           )
                      /natoms);
    // Rotation matrix is dot(U,V)
    std::vector<float> M(9,0);
    sgemm('N','N',3,3,3,1,&U[0],3,&V[0],3,1,&M[0],3);
    /*
     M = [ 0 3 6 ] = [ 00 01 02 ]
         [ 1 4 7 ]   [ 10 11 12 ]
         [ 2 5 8 ]   [ 20 21 22 ]
     */
    float trace = M[0]+M[4]+M[8];
    float angle = acos((trace-1)/2)*RAD2DEG;
    float rx,ry,rz,ux,uy,uz;
    rx = atan2(M[5],M[8])*RAD2DEG;
    ry = atan2(-M[2],sqrt(M[5]*M[5]+M[8]*M[8]))*RAD2DEG;
    rz = atan2(M[1],M[0])*RAD2DEG;
    float zeta = sqrt(
                        (M[5]-M[7])*(M[5]-M[7])
                      + (M[6]-M[2])*(M[6]-M[2])
                      + (M[3]-M[1])*(M[3]-M[1])
                      );
    //std::cout << "\n" << M[5] << " - " << M[7] << " = " << M[5]-M[7];
    //std::cout << "\n" << M[6] << " - " << M[2] << " = " << M[6]-M[2];
    //std::cout << "\n" << M[3] << " - " << M[1] << " = " << M[3]-M[1] << std::endl;
    ux = (M[5]-M[7])/zeta;
    uy = (M[6]-M[2])/zeta;
    uz = (M[3]-M[1])/zeta;
    //std::cout << zeta << " { " << ux << " " << uy << " " << uz << " }" << sqrt(ux*ux+uy*uy+uz*uz) << std:: endl;
    if (bVerbose)
    {
        fprintf(stdout,"%12s%12s%12s%12s%12s%12s%12s%12s\n","Angle(deg)","rmsd(nm)","x(deg)","y(deg)","z(deg)","ux(nm)","uy(nm)","uz(nm)");
        fprintf(stdout,"%12.3f%12.6f%12.4f%12.4f%12.4f%12.4f%12.4f%12.4f\n",angle,rmsd,rx,ry,rz,ux,uy,uz);
    }
    data.rotation.push_back(angle);
    data.rmsd.push_back(rmsd);
    data.x_rotation.push_back(rx);
    data.y_rotation.push_back(ry);
    data.z_rotation.push_back(rz);
    data.x_rotation_axis.push_back(ux);
    data.y_rotation_axis.push_back(uy);
    data.z_rotation_axis.push_back(uz);

    return;
}