/* Program RMS written by Scott M. Le Grand Even more modified and completely changed in 1999 by Arne Elofsson Modified by Arne Elofsson in 1994 Copyright 1992, Scott M. Le Grand */ #include #include #ifdef NOZLIB #else #include #endif #include #include #include #include #define MAXATMS 5000 /* Maximum allowable atoms */ #define PI 3.14159265 /* Useful constant */ #define TRUE 1 /* Boolean definitions */ #define FALSE 0 typedef struct { struct { double x,y,z; /* Atomic coordinates */ double rms; /* RMS deviation */ char residue[8]; /* PDB info for output */ char name[8]; int number; int resnum; int selected; } atm[MAXATMS]; double xcen,ycen,zcen; int atoms; /* Current # of atoms */ char filename[80]; /* filename to read molecule from */ } molecule; molecule m[2]; /* Molecules to be compared */ double LG_pvalue(); double Levitt_Gerstein(); double superimpose_molecules(); int b_flag; int align_flag; int select1_flag; int select2_flag; int verbose_flag; /* Verbose output flag */ int output_flag; /* Output flag */ int fraction_flag; /* Output flag */ char output_name[80]; /* Output name */ int output_flag_ca; /* Output flag */ char output_name_ca[80]; /* Output name */ int read_molecules_ca(); double rms; /* final RMS error */ /*int temp;*/ main(argc,argv) /* Main routine */ int argc; char *argv[]; { molecule m0,m1; int files; /* Number of files parsed */ int i,j,k; /* Counter variable */ int L=4; // Minimum length of fragment for FindMaxSub matching int minatoms=25; /* Variable for min no of atoms for P-value*/ double s[3][3]; /* Final transformation matrix */ double maxrmsd,minrmsd; double fraction=1; double numfrac=0; double maxpvalue=1,maxpvalue1=1.; double score,maxrms,maxrms1,maxscore,maxscore1; double pvalue; int maxatoms,maxpos,minpos,atoms; int maxsub_15=0; int maxsub_20=0; int maxsub_25=0; int maxsub_30=0; int maxsub_35=0; int maxselect1_0[MAXATMS],maxselect1_1[MAXATMS]; int maxselect2_0[MAXATMS],maxselect2_1[MAXATMS]; double bestsizescore[MAXATMS]; int maxatoms1; /* Initialize */ files=0; verbose_flag=FALSE; output_flag=FALSE; select2_flag=FALSE; select1_flag=FALSE; /* Parse command line for PDB files and options */ i=1; /* temp=1; */ while (i bestsizescore[j]){bestsizescore[j]=score;} } if (rms<1.5 && maxsub_15minatoms)){ if (fraction_flag){ printf("GOOD1:\t%.2f\t%d\t%.1f\t%.1f\t%e\n", (double)j/atoms,j,rms,score, pvalue); } //printf ("TEST:\t%d\t%f\t%f\t%f\n",m[0].atoms,pvalue,rms,score); maxpvalue=pvalue; maxatoms=j; maxrms=rms; maxscore=score; for (k=0;k5){ center_molecule(&m[0]); center_molecule(&m[1]); rms=superimpose_molecules(&m[0],&m[1],s); score=Levitt_Gerstein(&m[0],&m[1]); pvalue=LG_pvalue(atoms,score); if (b_flag){ if (score > bestsizescore[atoms]){bestsizescore[atoms]=score;} } if (rms<1.5 && maxsub_15minatoms)){ // printf ("TEST:\t%d\t%f\t%f\t%f\n",m[0].atoms,pvalue,rms,score); if (fraction_flag){ printf("GOOD2:\t%.2f\t%d\t%.1f\t%.1f\t%e\n", (double)atoms/m[0].atoms,atoms,rms,score, pvalue); } fraction-=numfrac; maxpvalue=pvalue; maxatoms=atoms; maxrms=rms; maxscore=score; for (k=0;k maxrmsd){ maxpos=i; maxrmsd=m[0].atm[i].rms; } } // delete_atom(&m[0],maxpos); // delete_atom(&m[1],maxpos); //printf("Unselecting:\t%d\t%f\n",maxpos,maxrmsd); if(maxpos<0){printf ("ERROR2, not selecting any atom %d\n",i);} else{ m[0].atm[maxpos].selected=FALSE; m[1].atm[maxpos].selected=FALSE; } atoms--; } //printf("BEST2:\t%.2f\t%d\t%.1f\t%.1f\t%e\t%e\n", //(double)maxatoms/(double)m[0].atoms,maxatoms,maxrms,maxscore,maxpvalue,maxpvalue1); if (maxpvalue >= maxpvalue1 || select1_flag){ if (maxatoms1atoms;i++){ if (m->atm[i].selected){ xcen+=m->atm[i].x; ycen+=m->atm[i].y; zcen+=m->atm[i].z; natoms++; } } /* Now center molecule */ xcen/=(double)natoms; ycen/=(double)natoms; zcen/=(double)natoms; //printf("TEST natoms: %d %f %f %f \n",natoms,xcen,ycen,zcen); for (i=0;iatoms;i++) { m->atm[i].x-=xcen; m->atm[i].y-=ycen; m->atm[i].z-=zcen; } return(0); } multiply_matrix(a,b,c) /* computes C=AB */ double a[3][3],b[3][3],c[3][3]; { int i,j,k; for (i=0;i<3;i++) for (j=0;j<3;j++) { c[i][j]=0.0; for (k=0;k<3;k++) c[i][j]+=a[i][k]*b[k][j]; } } copy_matrix(f,t) /* copy matrix f into matrix t */ double f[3][3],t[3][3]; { int i,j; for (i=0;i<3;i++) for (j=0;j<3;j++) t[i][j]=f[i][j]; } transpose_matrix(m) /* Transpose a 3x3 matrix */ double m[3][3]; { double dummy; dummy=m[0][1]; m[0][1]=m[1][0]; m[1][0]=dummy; dummy=m[0][2]; m[0][2]=m[2][0]; m[2][0]=dummy; dummy=m[1][2]; m[1][2]=m[2][1]; m[2][1]=dummy; } delete_atom(m1,num) molecule *m1; int num; { int i,j,k; for (i=num;iatoms;i++) { j=i+1; strcpy(m1->atm[i].name,m1->atm[j].name); strcpy(m1->atm[i].residue,m1->atm[j].residue); m1->atm[i].x=m1->atm[j].x; m1->atm[i].y=m1->atm[j].y; m1->atm[i].z=m1->atm[j].z; /* m1->atm[i].rms=m1->atm[j].rms; */ m1->atm[i].number=m1->atm[j].number; m1->atm[i].resnum=m1->atm[j].resnum; } m1->atoms--; } check_molecules(m1,m2) molecule *m1,*m2; { /* this will delete all atoms that are not in both molecules */ /* Now we should extract the part of the molecules that exists in both */ int i,j,minlength; int found; minlength=m1->atoms; if (minlength>m1->atoms) minlength=m2->atoms; i=0; while (i<=m1->atoms && i<=m2->atoms ){ while ( m1->atm[i].resnum < m2->atm[i].resnum && i< m1->atoms ){ // printf("Deleting m1: %d %d %d\n",i,m1->atm[i].resnum,m2->atm[i].resnum); delete_atom(m1,i); } while (m1->atm[i].resnum > m2->atm[i].resnum && i< m2->atoms ){ // printf("Deleting m2: %d %d %d\n",i,m1->atm[i].resnum,m2->atm[i].resnum); delete_atom(m2,i); } i++; } while (m1->atoms < m2->atoms){ delete_atom(m2,m2->atoms) ;} while (m1->atoms > m2->atoms){ delete_atom(m1,m1->atoms) ;} } double Levitt_Gerstein(m1,m2) molecule *m1,*m2; { int i,j,last1,last2; int numgap=0; double sum=0.; // double d0=25.; // 5**2 double d0=5.; // 2.24**2 double M=20.; last1=m1->atm[0].resnum-1; last2=m2->atm[0].resnum-1; j=0; for (i=0;iatoms;i++) { if (m1->atm[i].selected){ last1++; last2++; if (m1->atm[i].resnum > last1 || m2->atm[i].resnum > last2 ){ numgap++; } sum+=(1/(1+m1->atm[i].rms/d0)); // printf("Test>\t%d\t%f\t%f\n",numgap,sum,m1->atm[i].rms); last1=m1->atm[i].resnum; last2=m2->atm[i].resnum; j++; // printf("Test> %d \t%d\t%d\t%f\n",i,m1->atm[i].selected,sum); } } //printf("TEST-LG>\t%d\t%d\t%f\t%f\n",j,numgap,sum,M*(sum-numgap/2)); return(M*(sum-numgap/2)); } double LG_pvalue(N,MS) int N; double MS; { double min_SD=1.e-20; double ln,Mean_MS,SD_MS,Z,expZ; double ln60=log(120.); double b=2.0*ln60*18.411424-4.501719; double a=(ln60*ln60)*18.411424+ln60*(-4.501719)+2.637163-b*ln60; if (N<6) { expZ=1.; return(expZ); } ln=log((double)N); if (N<120){ Mean_MS=ln*ln*18.411424+ln*(-4.501719)+ 2.637163; SD_MS=ln*21.351857 -37.521269; }else{ Mean_MS=ln*b+a; SD_MS=ln60*21.351857 -37.521269; } // if (SD_MS %d\t%f\t%f\t%e\t%e\t%e\t%e\n",N,MS,Mean_MS,SD_MS,Z,expZ,1-exp(-1*expZ)); if (Z>20){ return(expZ); // }else if (Z<-100){ //expZ=1.; //return(expZ); }else{ return(1-exp(-expZ)); } } double superimpose_molecules(m1,m2,s) /* Find RMS superimposition of m1 on m2 */ molecule *m1,*m2; /* Molecules to be superimposed */ double s[3][3]; /* Final transformation matrix */ { int i,j,k; /* Counter variables */ int natoms=0; double u[3][3]; /* direct product matrix */ double t[3][3]; /* Temporary storage matrix */ double ma[3][3]; /* x axis rotation matrix */ double mb[3][3]; /* y axis rotation matrix */ double mg[3][3]; /* z axis rotation matrix */ double *d1,*d2; /* usefule pointers */ double error; /* Final superimposition error */ double error2; /* Final superimposition error */ double alpha=0.0; /* Angle of rotation around x axis */ double beta=0.0; /* Angle of rotation around y axis */ double gamma=0.0; /* Angle of rotation around z axis */ double dist,dist2,x,y,z; /* Temporary coordinate variables */ for (i=0;i<3;i++) /* Initialize matrices */ for (j=0;j<3;j++) s[i][j]=u[i][j]=0.0; s[0][0]=s[1][1]=s[2][2]=1.0; /* Initialize S matrix to I */ for (i=0;i<3;i++) /* Initialize rotation matrices to I */ for (j=0;j<3;j++) ma[i][j]=mb[i][j]=mg[i][j]=s[i][j]; for (i=0;iatoms;i++) /* Construct U matrix */ { if (m1->atm[i].selected){ d1= &(m1->atm[i].x); for (j=0;j<3;j++) { d2= &(m2->atm[i].x); for (k=0;k<3;k++) { u[j][k]+=(*d1)*(*d2); d2++; } d1++; } } } do { error=0.0; /* Calculate x axis rotation */ alpha=atan((u[2][1]-u[1][2])/(u[1][1]+u[2][2])); /* Insure we are heading for a minimum, not a maximum */ if (cos(alpha)*(u[1][1]+u[2][2])+sin(alpha)*(u[2][1]-u[1][2])<0.0) alpha+=PI; ma[1][1]=ma[2][2]=cos(alpha); ma[2][1]=sin(alpha); ma[1][2]= -ma[2][1]; transpose_matrix(ma); multiply_matrix(u,ma,t); transpose_matrix(ma); copy_matrix(t,u); multiply_matrix(ma,s,t); copy_matrix(t,s); /* Calculate y axis rotation */ beta=atan((u[0][2]-u[2][0])/(u[0][0]+u[2][2])); /* Insure we are heading for a minimum, not a maximum */ if (cos(beta)*(u[0][0]+u[2][2])+sin(beta)*(u[0][2]-u[2][0])<0.0) beta+=PI; mb[0][0]=mb[2][2]=cos(beta); mb[0][2]=sin(beta); mb[2][0]= -mb[0][2]; transpose_matrix(mb); multiply_matrix(u,mb,t); transpose_matrix(mb); copy_matrix(t,u); multiply_matrix(mb,s,t); copy_matrix(t,s); /* Calculate z axis rotation */ gamma=atan((u[1][0]-u[0][1])/(u[0][0]+u[1][1])); /* Insure we are heading for a minimum, not a maximum */ if (cos(gamma)*(u[0][0]+u[1][1])+sin(gamma)*(u[1][0]-u[0][1])<0.0) gamma+=PI; mg[0][0]=mg[1][1]=cos(gamma); mg[1][0]=sin(gamma); mg[0][1]= -mg[1][0]; transpose_matrix(mg); multiply_matrix(u,mg,t); transpose_matrix(mg); copy_matrix(t,u); multiply_matrix(mg,s,t); copy_matrix(t,s); error=fabs(alpha)+fabs(beta)+fabs(gamma); } while (error>0.0001); /* Is error low enough to stop? */ /* Now calculate final RMS superimposition */ error=0.0; error2=0.0; natoms=0; /* printf("testing7b %f %f\n",m2->atm[1].x,error); printf ("s1:\t%f\t%f\t%f\n",s[0][0],s[0][1],s[0][2]); printf ("s2:\t%f\t%f\t%f\n",s[1][0],s[1][1],s[1][2]); printf ("s3:\t%f\t%f\t%f\n",s[2][0],s[2][1],s[2][2]);*/ if (! (s[0][0]>0 || s[0][0]<0)) { // printf ("bar\n"); for (i=0;i<3;i++) /* Initialize matrices */ for (j=0;j<3;j++) s[i][j]=u[i][j]=0.0; s[0][0]=s[1][1]=s[2][2]=1.0; /* Initialize S matrix to I */ } for (i=0;iatoms;i++) { dist=m2->atm[i].x*m2->atm[i].x+m2->atm[i].y*m2->atm[i].y+m2->atm[i].z*m2->atm[i].z; // printf("TEST1-m2\t %d\t%6.3f %6.3f %6.3f\t%e\n",i,m2->atm[i].x,m2->atm[i].y,m2->atm[i].z,dist); x=s[0][0]*m2->atm[i].x+s[0][1]*m2->atm[i].y+s[0][2]*m2->atm[i].z; y=s[1][0]*m2->atm[i].x+s[1][1]*m2->atm[i].y+s[1][2]*m2->atm[i].z; z=s[2][0]*m2->atm[i].x+s[2][1]*m2->atm[i].y+s[2][2]*m2->atm[i].z; m2->atm[i].x=x; m2->atm[i].y=y; m2->atm[i].z=z; //dist2=m2->atm[i].x*m2->atm[i].x+m2->atm[i].y*m2->atm[i].y+m2->atm[i].z*m2->atm[i].z; //printf("TEST2-m2\t %d\t%6.3f %6.3f %6.3f\t%e\t%e\n",i,m2->atm[i].x,m2->atm[i].y,m2->atm[i].z,dist2,dist2-dist); x=m1->atm[i].x-x; y=m1->atm[i].y-y; z=m1->atm[i].z-z; m2->atm[i].rms=m1->atm[i].rms=x*x+y*y+z*z; error+=m1->atm[i].rms; if (m1->atm[i].selected){ error2+=m1->atm[i].rms; natoms++; } /*printf ("TEST1: %f %f %f\n",m1->atm[i].x,m1->atm[i].y,m1->atm[i].z); printf ("TEST2: %f %f %f\n",m2->atm[i].x,m2->atm[i].y,m2->atm[i].z); printf ("TEST3: %d %f %f\n",i,error,m1->atm[i].rms); */ } // printf("testing8 %f\n",m2->atm[1].x); error/=(double)(m1->atoms); error2/=(double)(natoms); return(sqrt(error2)); } output_results() { int i,j; /* Counter variable */ double sum; /* Average RMS counter by residue */ double resatoms; /* Number of atoms in each residue */ char name[8]; /* Temporary residue name variable */ printf("Overall average RMS deviation is %lf Angstroms.\n",rms); /* First output RMS deviations by atom */ printf("\n"); printf("RMS deviations by atom\n"); printf("Atom \t Name \t residue \t RMS deviation\tAtom \t Name \t residue \t RMS deviation\n"); for (i=0;i