diff --git a/CMakeLists.txt b/CMakeLists.txt index 65049c6b76b74a8c8c37edb6f925efa9c9b5e030..53cb659a5ca0902bd379c53f5705022ae1e9ccf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ project(OpenStructure CXX C) option(USE_SHADER "whether to compile with shader support" OFF) +option(COMPILE_TMTOOLS "whether to compile the tmalign and tmscore programs" + OFF) option(PROFILE "whether to compile with profiling support" OFF) option(ENABLE_GUI "whether the graphical user interface should be enabled" diff --git a/modules/bindings/CMakeLists.txt b/modules/bindings/CMakeLists.txt index c274b8004ed448411dc29ea5da16d12e2a094702..cf7db32255f81caf33d038075ff8acd63d86a4e7 100644 --- a/modules/bindings/CMakeLists.txt +++ b/modules/bindings/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(pymod) add_subdirectory(tests) +add_subdirectory(src) \ No newline at end of file diff --git a/modules/bindings/src/CMakeLists.txt b/modules/bindings/src/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3c178c5f3b7d0158a90e8e1f14d1b21242ec18e4 --- /dev/null +++ b/modules/bindings/src/CMakeLists.txt @@ -0,0 +1,5 @@ +if (COMPILE_TMTOOLS) + enable_language(Fortran) + executable(NAME tmalign SOURCES tmalign.f NO_RPATH) + executable(NAME tmscore SOURCES tmscore.f NO_RPATH) +endif() \ No newline at end of file diff --git a/modules/bindings/src/tmalign.f b/modules/bindings/src/tmalign.f new file mode 100644 index 0000000000000000000000000000000000000000..73bbd905d13d4196da88392504a7475abc1fc3a4 --- /dev/null +++ b/modules/bindings/src/tmalign.f @@ -0,0 +1,2896 @@ +************************************************************************* +* This program is to identify the best alignment of two protein +* structures to give the best TM-score. By default, TM-score is +* normalized by the second protein. The program can be freely +* copied or modified or redistributed. +* (For comments, please email to: zhng@umich.edu) +* +* Reference: +* Yang Zhang, Jeffrey Skolnick, Nucl. Acid Res. 2005 33: 2303-9 +* +************************ updating history ******************************* +* 2005/06/01: A small bug of two-point superposition was fixed. +* 2005/10/19: the program was reformed so that the alignment +* results are not dependent on the specific compilers. +* 2006/06/20: select 'A' if there is altLoc when reading PDB file. +* 2007/02/27: rotation matrix from Chain-1 to Chain-2 is added. +* 2007/04/18: add options with TM-score normalized by average +* length, shorter length, or longer length of two +* structures. +* 2007/05/23: add additional output file 'TM.sup_all' for showing +* all atoms while 'TM.sup' is only for aligned atoms +* 2007/09/19: add a new feature alignment to deal with the problem +* of aligning fractional structures (e.g. protein +* interfaces). +* 2007/10/16: A bug for irregular bond-length models was fixed. +* 2009/03/14: A new initial alignment is added and previous initial +* alignments are further enhanced. This change increases +* accuracy by 4% but increases CPU cost by 40%. +* 2009/08/20: A bug for asymmetry alignment result was fixed. +* +************************************************************************* + + program compares + PARAMETER(nmax=5000) + PARAMETER(nmax2=10000) + + COMMON/BACKBONE/XA(3,nmax,0:1) + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/length/nseq1,nseq2 + common/d0/d0,anseq + common/d0min/d0_min + common/d00/d00,d002 + + character*100 fnam,pdb(100),outname + character*3 aa(-1:20),aanam,ss1(nmax),ss2(nmax) + character*100 s,du + character*200 outnameall_tmp,outnameall + character seq1(0:nmax),seq2(0:nmax) + character aseq1(nmax2),aseq2(nmax2),aseq3(nmax2) + + dimension xx(nmax),yy(nmax),zz(nmax) + dimension m1(nmax),m2(nmax) + dimension xtm1(nmax),ytm1(nmax),ztm1(nmax) + dimension xtm2(nmax),ytm2(nmax),ztm2(nmax) + common/init/invmap_i(nmax) + + common/TM/TM,TMmax + common/n1n2/n1(nmax),n2(nmax) + common/d8/d8 + common/initial4/mm1(nmax),mm2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + + data aa/ 'BCK','GLY','ALA','SER','CYS', + & 'VAL','THR','ILE','PRO','MET', + & 'ASP','ASN','LEU','LYS','GLU', + & 'GLN','ARG','HIS','PHE','TYR', + & 'TRP','CYX'/ + character*1 slc(-1:20) + data slc/'X','G','A','S','C', + & 'V','T','I','P','M', + & 'D','N','L','K','E', + & 'Q','R','H','F','Y', + & 'W','C'/ + + call getarg(1,fnam) + if(fnam.eq.' '.or.fnam.eq.'?'.or.fnam.eq.'-h')then + write(*,*) + write(*,*)'Brief instruction for running TM-align program:' + write(*,*)'(For detail: Zhang & Skolnick, Nucl. Acid. Res.', + & ' 33, 2303, 2005)' + write(*,*) + write(*,*)'1. Align ''structure.pdb'' to ''target.pdb''' + write(*,*)' (By default, TM-score is normalized by the ', + & 'length of ''target.pdb'')' + write(*,*)' >TMalign structure.pdb target.pdb' + write(*,*) + write(*,*)'2. Run TM-align and output the superposition ', + & 'to ''TM.sup'' and ''TM.sup_all'':' + write(*,*)' >TMalign structure.pdb target.pdb -o TM.sup' + write(*,*)' To view the superimposed structures of the', + & ' aligned regions by rasmol:' + write(*,*)' >rasmol -script TM.sup)' + write(*,*)' To view the superimposed structures of all', + & ' regions by rasmol:' + write(*,*)' >rasmol -script TM.sup_all)' + write(*,*) + write(*,*)'3. If you want TM-score normalized by ', + & 'an assigned length, e.g. 100 aa:' + write(*,*)' >TMalign structure.pdb target.pdb -L 100' + write(*,*)' If you want TM-score normalized by the ', + & 'average length of two structures:' + write(*,*)' >TMalign structure.pdb target.pdb -a' + write(*,*)' If you want TM-score normalized by the ', + & 'shorter length of two structures:' + write(*,*)' >TMalign structure.pdb target.pdb -b' + write(*,*)' If you want TM-score normalized by the ', + & 'longer length of two structures:' + write(*,*)' >TMalign structure.pdb target.pdb -c' + write(*,*) +c write(*,*)'5. If you want to set a minimum cutoff for d0, ', +c & 'e.g. d0>3.0' +c write(*,*)' (By default d0>0.5, this option need ', +c & 'be considered only when L<35 aa)' +c write(*,*)' >TMalign structure.pdb target.pdb -dmin 3.0' +c write(*,*) + write(*,*)'(All above options do not change the ', + & 'final structure alignment result)' + write(*,*) + goto 9999 + endif + +******* options -----------> + m_out=-1 !decided output + m_fix=-1 !fixed length-scale only for output + m_ave=-1 !using average length + m_d0_min=-1 !diminum d0 for search + m_d0=-1 !given d0 for both search and output + narg=iargc() + i=0 + j=0 + 115 continue + i=i+1 + call getarg(i,fnam) + if(fnam.eq.'-o')then + m_out=1 + i=i+1 + call getarg(i,outname) + elseif(fnam.eq.'-L')then !change both L_all and d0 + m_fix=1 + i=i+1 + call getarg(i,fnam) + read(fnam,*)L_fix + elseif(fnam.eq.'-dmin')then + m_d0_min=1 + i=i+1 + call getarg(i,fnam) + read(fnam,*)d0_min_input + elseif(fnam.eq.'-d0')then + m_d0=1 + i=i+1 + call getarg(i,fnam) + read(fnam,*)d0_fix + elseif(fnam.eq.'-a')then ! this will change the superposed output but not the alignment + m_ave=1 + i=i+1 + elseif(fnam.eq.'-b')then + m_ave=2 + i=i+1 + elseif(fnam.eq.'-c')then + m_ave=3 + i=i+1 + else + j=j+1 + pdb(j)=fnam + endif + if(i.lt.narg)goto 115 + +ccccccccc read data from first CA file: + open(unit=10,file=pdb(1),status='old') + i=0 + do while (.true.) + read(10,9001,end=1010) s + if(i.gt.0.and.s(1:3).eq.'TER')goto 1010 + if(s(1:3).eq.'ATO')then + if(s(13:16).eq.'CA '.or.s(13:16).eq.' CA '.or + & .s(13:16).eq.' CA')then + if(s(17:17).eq.' '.or.s(17:17).eq.'A')then + i=i+1 + read(s,9000)du,aanam,du,mm1(i),du, + $ xa(1,i,0),xa(2,i,0),xa(3,i,0) + do j=-1,20 + if(aanam.eq.aa(j))then + seq1(i)=slc(j) + goto 21 + endif + enddo + seq1(i)=slc(-1) + 21 continue + ss1(i)=aanam + if(i.ge.nmax)goto 1010 + endif + endif + endif + enddo + 1010 continue + 9000 format(A17,A3,A2,i4,A4,3F8.3) + 9001 format(A100) + close(10) + nseq1=i +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ccccccccc read data from the second CA file: + open(unit=10,file=pdb(2),status='old') + i=0 + do while (.true.) + read(10,9001,end=1011) s + if(i.gt.0.and.s(1:3).eq.'TER')goto 1011 + if(s(1:3).eq.'ATO')then + if(s(13:16).eq.'CA '.or.s(13:16).eq.' CA '.or. + & s(13:16).eq.' CA')then + if(s(17:17).eq.' '.or.s(17:17).eq.'A')then + i=i+1 + read(s,9000)du,aanam,du,mm2(i),du, + $ xa(1,i,1),xa(2,i,1),xa(3,i,1) + do j=-1,20 + if(aanam.eq.aa(j))then + seq2(i)=slc(j) + goto 22 + endif + enddo + seq2(i)=slc(-1) + 22 continue + ss2(i)=aanam + if(i.ge.nmax)goto 1011 + endif + endif + endif + enddo + 1011 continue + close(10) + nseq2=i +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*!!! Scale of TM-score in search is based on the smaller protein ---------> + d0_min=0.5 + if(m_d0_min.eq.1)then + d0_min=d0_min_input !for search + endif + anseq_min=min(nseq1,nseq2) + anseq=anseq_min !length for defining TMscore in search + d8=1.5*anseq_min**0.3+3.5 !remove pairs with dis>d8 during search & final + if(anseq.gt.15)then + d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score + else + d0=d0_min + endif + if(d0.lt.d0_min)d0=d0_min + if(m_d0.eq.1)d0=d0_fix + d00=d0 !for quickly calculate TM-score in searching + if(d00.gt.8)d00=8 + if(d00.lt.4.5)d00=4.5 + d002=d00**2 + nseq=max(nseq1,nseq2) + do i=1,nseq + n1(i)=i + n2(i)=i + enddo + +***** do alignment ************************** + CALL super_align !to find invmap(j) + +************************************************************ +*** resuperpose to find residues of dis<d8 ------------------------> + n_al=0 + do j=1,nseq2 + if(invmap0(j).gt.0)then + i=invmap0(j) + n_al=n_al+1 + xtm1(n_al)=xa(1,i,0) + ytm1(n_al)=xa(2,i,0) + ztm1(n_al)=xa(3,i,0) + xtm2(n_al)=xa(1,j,1) + ytm2(n_al)=xa(2,j,1) + ztm2(n_al)=xa(3,j,1) + m1(n_al)=i !for recording residue order + m2(n_al)=j + endif + enddo + d0_input=d0 + call TMscore8(d0_input,n_al,xtm1,ytm1,ztm1,n1,n_al, + & xtm2,ytm2,ztm2,n2,TM,Rcomm,Lcomm) !TM-score with dis<d8 only + +*!!! Output TM-score is based on the second protein------------------> + d0_min=0.5 !for output + anseq=nseq2 !length for defining final TMscore + if(m_ave.eq.1)anseq=(nseq1+nseq2)/2.0 !<L> + if(m_ave.eq.2)anseq=min(nseq1,nseq2) + if(m_ave.eq.3)anseq=max(nseq1,nseq2) + if(anseq.lt.anseq_min)anseq=anseq_min + if(m_fix.eq.1)anseq=L_fix !input length + if(anseq.gt.15)then + d0=1.24*(anseq-15)**(1.0/3.0)-1.8 !scale for defining TM-score + else + d0=d0_min + endif + if(d0.lt.d0_min)d0=d0_min + if(m_d0.eq.1)d0=d0_fix + +*** remove dis>d8 in normal TM-score calculation for final report-----> + j=0 + n_eq=0 + do i=1,n_al + dis2=sqrt((xtm1(i)-xtm2(i))**2+(ytm1(i)-ytm2(i))**2+ + & (ztm1(i)-ztm2(i))**2) + if(dis2.le.d8)then + j=j+1 + xtm1(j)=xtm1(i) + ytm1(j)=ytm1(i) + ztm1(j)=ztm1(i) + xtm2(j)=xtm2(i) + ytm2(j)=ytm2(i) + ztm2(j)=ztm2(i) + m1(j)=m1(i) + m2(j)=m2(i) + if(ss1(m1(i)).eq.ss2(m2(i)))then + n_eq=n_eq+1 + endif + endif + enddo + seq_id=float(n_eq)/(n_al+0.00000001) + n8_al=j + d0_input=d0 + call TMscore(d0_input,n8_al,xtm1,ytm1,ztm1,n1,n8_al, + & xtm2,ytm2,ztm2,n2,TM8,Rcomm,Lcomm) !normal TMscore + rmsd8_al=Rcomm + TM8=TM8*n8_al/anseq !TM-score after cutoff + + + +********* for output summary ****************************** + write(*,*) + write(*,*)'*****************************************************', + & '*********************' + write(*,*)'* TM-align ', + & ' *' + write(*,*)'* A protein structural alignment algorithm based on T', + & 'M-score *' + write(*,*)'* Reference: Y. Zhang and J. Skolnick, Nucl. Acids Re', + & 's. 2005 33, 2302-9 *' + write(*,*)'* Comments on the program, please email to: yzhang@ku', + & '.edu *' + write(*,*)'*****************************************************', + & '*********************' + write(*,*) + write(*,101)pdb(1),nseq1 + 101 format('Chain 1:',A10,' Size=',I4) + write(*,102)pdb(2),nseq2,int(anseq) + 102 format('Chain 2:',A10,' Size=',I4, + & ' (TM-score is normalized by ',I4,')') + write(*,*) + write(*,103)n8_al,rmsd8_al,TM8,seq_id + 103 format('Aligned length=',I4,', RMSD=',f6.2, + & ', TM-score=',f7.5,', ID=',f5.3) + write(*,*) + +********* extract rotation matrix ------------> + L=0 + do i=1,n8_al + k=m1(i) + L=L+1 + r_1(1,L)=xa(1,k,0) + r_1(2,L)=xa(2,k,0) + r_1(3,L)=xa(3,k,0) + r_2(1,L)=xtm1(i) + r_2(2,L)=ytm1(i) + r_2(3,L)=ztm1(i) + enddo + if(L.gt.3)then + call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2 + armsd=dsqrt(rms/L) + write(*,*)'-------- rotation matrix to rotate Chain-1 to ', + & 'Chain-2 ------' + write(*,*)'i t(i) u(i,1) u(i,2) ', + & ' u(i,3)' + do i=1,3 + write(*,204)i,t(i),u(i,1),u(i,2),u(i,3) + enddo +c do i=1,nseq1 +c ax=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0) +c ay=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0) +c az=t(3)+u(3,1)*xa(1,i,0)+u(3,2)*xa(2,i,0)+u(3,3)*xa(3,i,0) +c enddo + write(*,*) + endif + 204 format(I2,f18.10,f15.10,f15.10,f15.10) + +********* for output superposition ****************************** + if(m_out.eq.1)then + 1237 format('ATOM ',i5,' CA ',A3,I6,4X,3F8.3) + 1238 format('TER') + 1239 format('CONECT',I5,I5) + 900 format(A) + 901 format('select atomno=',I4) + 104 format('REMARK Chain 1:',A10,' Size=',I4) + 105 format('REMARK Chain 2:',A10,' Size=',I4, + & ' (TM-score is normalized by ',I4,')') + 106 format('REMARK Aligned length=',I4,', RMSD=',f6.2, + & ', TM-score=',f7.5,', ID=',f5.3) + OPEN(unit=7,file=outname,status='unknown') !pdb1.aln + pdb2.aln +*** script: + write(7,900)'load inline' + write(7,900)'select atomno<2000' + write(7,900)'wireframe .45' + write(7,900)'select none' + write(7,900)'select atomno>2000' + write(7,900)'wireframe .20' + write(7,900)'color white' + do i=1,n8_al + dis2=sqrt((xtm1(i)-xtm2(i))**2+ + & (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2) + if(dis2.le.5)then + write(7,901)m1(i) + write(7,900)'color red' + write(7,901)2000+m2(i) + write(7,900)'color red' + endif + enddo + write(7,900)'select all' + write(7,900)'exit' + write(7,104)pdb(1),nseq1 + write(7,105)pdb(2),nseq2,int(anseq) + write(7,106)n8_al,rmsd8_al,TM8,seq_id +*** chain1: + do i=1,n8_al + write(7,1237)m1(i),ss1(m1(i)),mm1(m1(i)), + & xtm1(i),ytm1(i),ztm1(i) + enddo + write(7,1238) !TER + do i=2,n8_al + write(7,1239)m1(i-1),m1(i) !connect atoms + enddo +*** chain2: + do i=1,n8_al + write(7,1237)2000+m2(i),ss2(m2(i)),mm2(m2(i)), + $ xtm2(i),ytm2(i),ztm2(i) + enddo + write(7,1238) + do i=2,n8_al + write(7,1239)2000+m2(i-1),2000+m2(i) + enddo + close(7) +ccc + k=0 + outnameall_tmp=outname//'_all' + outnameall='' + do i=1,200 + if(outnameall_tmp(i:i).ne.' ')then + k=k+1 + outnameall(k:k)=outnameall_tmp(i:i) + endif + enddo + OPEN(unit=8,file=outnameall,status='unknown') !pdb1.aln + pdb2.aln +*** script: + write(8,900)'load inline' + write(8,900)'select atomno<2000' + write(8,900)'wireframe .45' + write(8,900)'select none' + write(8,900)'select atomno>2000' + write(8,900)'wireframe .20' + write(8,900)'color white' + do i=1,n8_al + dis2=sqrt((xtm1(i)-xtm2(i))**2+ + & (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2) + if(dis2.le.5)then + write(8,901)m1(i) + write(8,900)'color red' + write(8,901)2000+m2(i) + write(8,900)'color red' + endif + enddo + write(8,900)'select all' + write(8,900)'exit' + write(8,104)pdb(1),nseq1 + write(8,105)pdb(2),nseq2,int(anseq) + write(8,106)n8_al,rmsd8_al,TM8,seq_id +*** chain1: + do i=1,nseq1 + ax=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0) + ay=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0) + az=t(3)+u(3,1)*xa(1,i,0)+u(3,2)*xa(2,i,0)+u(3,3)*xa(3,i,0) + write(8,1237)i,ss1(i),mm1(i),ax,ay,az + enddo + write(8,1238) !TER + do i=2,nseq1 + write(8,1239)i-1,i + enddo +*** chain2: + do i=1,nseq2 + write(8,1237)2000+i,ss2(i),mm2(i), + $ xa(1,i,1),xa(2,i,1),xa(3,i,1) + enddo + write(8,1238) + do i=2,nseq2 + write(8,1239)2000+i-1,2000+i + enddo + close(8) + endif +*^^^^^^^^^^^^^^^^^^ output finished ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +************ output aligned sequences ************************** + ii=0 + i1_old=1 + i2_old=1 + do i=1,n8_al + do j=i1_old,m1(i)-1 + ii=ii+1 + aseq1(ii)=seq1(j) + aseq2(ii)='-' + aseq3(ii)=' ' + enddo + do j=i2_old,m2(i)-1 + ii=ii+1 + aseq1(ii)='-' + aseq2(ii)=seq2(j) + aseq3(ii)=' ' + enddo + ii=ii+1 + aseq1(ii)=seq1(m1(i)) + aseq2(ii)=seq2(m2(i)) + dis2=sqrt((xtm1(i)-xtm2(i))**2+ + & (ytm1(i)-ytm2(i))**2+(ztm1(i)-ztm2(i))**2) + if(dis2.le.5)then + aseq3(ii)=':' + else + aseq3(ii)='.' + endif + i1_old=m1(i)+1 + i2_old=m2(i)+1 + enddo + do i=i1_old,nseq1 + ii=ii+1 + aseq1(ii)=seq1(i) + aseq2(ii)='-' + aseq3(ii)=' ' + enddo + do i=i2_old,nseq2 + ii=ii+1 + aseq1(ii)='-' + aseq2(ii)=seq2(i) + aseq3(ii)=' ' + enddo + write(*,50) + 50 format('(":" denotes the residue pairs of distance < 5.0 ', + & 'Angstrom)') + write(*,10)(aseq1(i),i=1,ii) + write(*,10)(aseq3(i),i=1,ii) + write(*,10)(aseq2(i),i=1,ii) + 10 format(10000A1) + write(*,*) + +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 9999 END + + +*********************************************************************** +*********************************************************************** +* Structure superposition +*********************************************************************** +*********************************************************************** +*********************************************************************** + SUBROUTINE super_align + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/init/invmap_i(nmax) + common/init1/invmap_ii(nmax) + dimension gapp(100) + + TMmax=0 + n_gapp=2 + gapp(1)=-0.6 + gapp(2)=0 + +c n_gapp=11 +c do i=1,n_gapp +c gapp(i)=-(n_gapp-i) +c enddo + +*11111111111111111111111111111111111111111111111111111111 +* get initial alignment from gapless threading +********************************************************** + call get_initial !gapless threading + do i=1,nseq2 + invmap(i)=invmap_i(i) !with highest zcore + enddo + call get_score !TM, matrix score(i,j) + + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + +***************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 111 i_gapp=1,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 222 id=1,30 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(id.gt.1)then + diff=abs(TM-TM_old) + if(diff.lt.0.000001)goto 33 + endif + TM_old=TM + 222 continue + 33 continue + 111 continue + + do i=1,nseq2 + invmap(i)=invmap_ii(i) !with highest zcore + enddo + call get_score !TM, matrix score(i,j) + + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(TM.le.TMmax*0.6)goto 51 +**************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 112 i_gapp=1,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 223 id=1,2 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) + !print *,"In1a",TM,TMmax +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(id.gt.1)then + diff=abs(TM-TM_old) + if(diff.lt.0.000001)goto 34 + endif + TM_old=TM + 223 continue + 34 continue + 112 continue + 51 continue + +*222222222222222222222222222222222222222222222222222222222 +* get initial alignment from secondary structure alignment +********************************************************** + call get_initial2 !DP for secondary structure + do i=1,nseq2 + invmap(i)=invmap_i(i) !with highest zcore + enddo + call get_score !TM, score(i,j) + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(TM.le.TMmax*0.2)goto 52 +***************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 1111 i_gapp=1,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 2222 id=1,30 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) +c write(*,21)gap_open,rmsd_al,n_al,TM +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(id.gt.1)then + diff=abs(TM-TM_old) + if(diff.lt.0.000001)goto 333 + endif + TM_old=TM + 2222 continue + 333 continue + 1111 continue + 52 continue + +*555555555555555555555555555555555555555555555555555555555555555555 +* get initial alignment of local structure superposition +******************************************************************* + call get_initial5 + do i=1,nseq2 + invmap(i)=invmap_i(i) !with highest zcore + enddo + call get_score !TM, matrix score(i,j) + + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(TM.le.TMmax*0.8)goto 53 +***************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 88 i_gapp=1,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 888 id=1,2 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) +c print *,"Ini5a",TM,TMmax +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(id.gt.1)then + diff=abs(TM-TM_old) + if(diff.lt.0.000001)goto 880 + endif + TM_old=TM + 888 continue + 880 continue + 88 continue + 53 continue + +*333333333333333333333333333333333333333333333333333333333333 +* get initial alignment from invmap0+SS +************************************************************* + call get_initial3 !invmap0+SS + do i=1,nseq2 + invmap(i)=invmap_i(i) !with highest zcore + enddo + call get_score !TM, score(i,j) + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(TM.le.TMmax*0.2)goto 54 +***************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 1110 i_gapp=1,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 2220 id=1,30 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) +c write(*,21)gap_open,rmsd_al,n_al,TM +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(id.gt.1)then + diff=abs(TM-TM_old) + if(diff.lt.0.000001)goto 330 + endif + TM_old=TM + 2220 continue + 330 continue + 1110 continue + 54 continue + +*444444444444444444444444444444444444444444444444444444444 +* get initial alignment of pieces from gapless threading +********************************************************** + call get_initial4 !gapless threading + do i=1,nseq2 + invmap(i)=invmap_i(i) !with highest zcore + enddo + do i=1,nseq2 + do j=1,nseq1 + score(i,j)=0 + enddo + enddo + + call get_score !TM, matrix score(i,j) + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + if(TM.le.TMmax*0.3)goto 55 +***************************************************************** +* initerative alignment, for different gap_open: +***************************************************************** + DO 44 i_gapp=2,n_gapp !different gap panalties + GAP_OPEN=gapp(i_gapp) !gap panalty + do 444 id=1,2 !maximum interation is 200 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) +* Input: score(i,j), and gap_open +* Output: invmap(j) + + call get_score !calculate TM-score, score(i,j) + ! print *,"Ini4a",TM,TMmax +c record the best alignment in whole search ----------> + if(TM.gt.TMmax)then + TMmax=TM + do j=1,nseq2 + invmap0(j)=invmap(j) + enddo + endif + 444 continue + 44 continue + 55 continue + +c^^^^^^^^^^^^^^^ best alignment invmap0(j) found ^^^^^^^^^^^^^^^^^^ + RETURN + END + +************************************************************** +* get initial alignment invmap0(i) from gapless threading +************************************************************** + subroutine get_initial + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/init/invmap_i(nmax) + common/init1/invmap_ii(nmax) + common/d0/d0,anseq + common/d0min/d0_min + common/speed/align_len1 + real n_cut + integer n_all + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms + data w /nmax*1.0/ + dimension xtmm1(nmax),ytmm1(nmax),ztmm1(nmax) + dimension xtmm2(nmax),ytmm2(nmax),ztmm2(nmax) + + d01=d0+1.5 + if(d01.lt.d0_min)d01=d0_min + d02=d01*d01 + + n_jump=1 + n_cut=0.99 + aL=min(nseq1,nseq2) + idel=aL/2.0 !minimum size of considered fragment + if(idel.le.5)idel=5 + n1=-nseq2+idel + n2=nseq1-idel + GL_max=0 + GL_maxA=0 + !GL_max_cut=0.99 + do ishift=n1,n2,n_jump + L=0 + do j=1,nseq2 + i=j+ishift + if(i.ge.1.and.i.le.nseq1)then + L=L+1 + invmap(j)=i + xtmm1(L)=xa(1,i,0) + ytmm1(L)=xa(1,i,0) + ztmm1(L)=xa(1,i,0) + xtmm2(L)=xa(1,j,1) + ytmm2(L)=xa(1,j,1) + ztmm2(L)=xa(1,j,1) + else + invmap(j)=-1 + endif + enddo + if(L.ge.idel)then + call get_GL(GL) + if(GL.gt.GL_max)then + + GL_max=GL + do i=1,nseq2 + invmap_i(i)=invmap(i) + enddo + endif + if(GL.gt.GL_max)then + !if(nseq1.le.nseq2)then + do ii=1,L + r_1(1,ii)=xtmm1(ii) + r_1(2,ii)=ytmm1(ii) + r_1(3,ii)=ztmm1(ii) + r_2(1,ii)=xtmm2(ii) + r_2(2,ii)=ytmm2(ii) + r_2(3,ii)=ztmm2(ii) + enddo + + call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2 + + do i1=1,nseq2 + xx=t(1)+u(1,1)*xa(1,i1,1)+u(1,2)*xa(2,i1,1)+u(1,3)* + & xa(3,i1,1) + yy=t(2)+u(2,1)*xa(1,i1,1)+u(2,2)*xa(2,i1,1)+u(2,3)* + & xa(3,i1,1) + zz=t(3)+u(3,1)*xa(1,i1,1)+u(3,2)*xa(2,i1,1)+u(3,3)* + & xa(3,i1,1) + do j1=1,nseq1 + dd=(xx-xa(1,j1,0))**2+(yy-xa(2,j1,0))**2+(zz-xa + & (3,j1,0))**2 + score(i1,j1)=1/(1+dd/d0) + enddo + enddo + +*********extract alignement with score(i,j) ***************** + align_len1=0 + call DP(NSEQ1,NSEQ2) + if(align_len1.gt.L*n_cut.and.align_len1.gt.idel)then + call get_GL(GL) + !print *,GL + if(GL.gt.GL_max.and.GL.gt.GL_maxA)then + GL_maxA=GL + do i1=1,aLL + invmap_ii(i1)=invmap(i1) + !print *,i,invmap_ii(i) + enddo + endif + endif + endif + endif + enddo + + return + end + +************************************************************** +* get initial alignment invmap0(i) from secondary structure +************************************************************** + subroutine get_initial2 + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/sec/isec(nmax),jsec(nmax) + common/init/invmap_i(nmax) + +********** assign secondary structures *************** +c 1->coil, 2->helix, 3->turn, 4->strand + do i=1,nseq1 + isec(i)=1 + j1=i-2 + j2=i-1 + j3=i + j4=i+1 + j5=i+2 + if(j1.ge.1.and.j5.le.nseq1)then + dis13=diszy(0,j1,j3) + dis14=diszy(0,j1,j4) + dis15=diszy(0,j1,j5) + dis24=diszy(0,j2,j4) + dis25=diszy(0,j2,j5) + dis35=diszy(0,j3,j5) + isec(i)=make_sec(dis13,dis14,dis15,dis24,dis25,dis35) + endif + enddo + do i=1,nseq2 + jsec(i)=1 + j1=i-2 + j2=i-1 + j3=i + j4=i+1 + j5=i+2 + if(j1.ge.1.and.j5.le.nseq2)then + dis13=diszy(1,j1,j3) + dis14=diszy(1,j1,j4) + dis15=diszy(1,j1,j5) + dis24=diszy(1,j2,j4) + dis25=diszy(1,j2,j5) + dis35=diszy(1,j3,j5) + jsec(i)=make_sec(dis13,dis14,dis15,dis24,dis25,dis35) + endif + enddo + call smooth !smooth the assignment + +********** score matrix ************************** + do i=1,nseq1 + do j=1,nseq2 + if(isec(i).eq.jsec(j))then + score(i,j)=1 + else + score(i,j)=0 + endif + enddo + enddo + +********** find initial alignment: invmap(j) ************ + gap_open=-1.0 !should be -1 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) + do i=1,nseq2 + invmap_i(i)=invmap(i) + enddo + +*^^^^^^^^^^^^ initial alignment done ^^^^^^^^^^^^^^^^^^^^^^ + return + end + +************************************************************** +* get initial alignment invmap0(i) from secondary structure +* and previous alignments +************************************************************** + subroutine get_initial3 + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/sec/isec(nmax),jsec(nmax) + common/init/invmap_i(nmax) + +********** score matrix ************************** + do i=1,nseq2 + invmap(i)=invmap0(i) + enddo + call get_score1 !get score(i,j) using RMSD martix + do i=1,nseq1 + do j=1,nseq2 + if(isec(i).eq.jsec(j))then + score(i,j)=0.5+score(i,j) + else + score(i,j)=score(i,j) + endif + enddo + enddo + +********** find initial alignment: invmap(j) ************ + gap_open=-1.0 !should be -1 + call DP(NSEQ1,NSEQ2) !produce alignment invmap(j) + do i=1,nseq2 + invmap_i(i)=invmap(i) + enddo + +*^^^^^^^^^^^^ initial alignment done ^^^^^^^^^^^^^^^^^^^^^^ + return + end + +************************************************************** +* get initial alignment invmap0(i) from fragment gapless threading +************************************************************** + subroutine get_initial4 + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/init/invmap_i(nmax) + common/initial4/mm1(nmax),mm2(nmax) + logical contin + + dimension ifr2(2,nmax,nmax),Lfr2(2,nmax),Lfr_max2(2),i_fr2(2) + dimension ifr(nmax) + dimension mm(2,nmax) + + fra_min=4 !>=4,minimum fragment for search + fra_min1=fra_min-1 !cutoff for shift, save time + dcu0=3.85 +c dcu_min=3.65 + +ccc Find the smallest continuous fragments --------> + do i=1,nseq1 + mm(1,i)=mm1(i) + enddo + do i=1,nseq2 + mm(2,i)=mm2(i) + enddo + do k=1,2 + dcu=dcu0 + if(k.eq.1)then + nseq0=nseq1 + r_min=nseq1/3.0 !minimum fragment, in case too small protein + else + nseq0=nseq2 + r_min=nseq2/3.0 !minimum fragment, in case too small protein + endif + if(r_min.gt.fra_min)r_min=fra_min + 20 nfr=1 !number of fragments + j=1 !number of residue at nf-fragment + ifr2(k,nfr,j)=1 !what residue + Lfr2(k,nfr)=j !length of the fragment + do i=2,nseq0 + dis=diszy(k-1,i-1,i) + contin=.false. + if(dcu.gt.dcu0)then + if(dis.lt.dcu)then +c if(dis.gt.dcu_min)then + contin=.true. +c endif + endif + elseif(mm(k,i).eq.(mm(k,i-1)+1))then + if(dis.lt.dcu)then +c if(dis.gt.dcu_min)then + contin=.true. +c endif + endif + endif + if(contin)then + j=j+1 + ifr2(k,nfr,j)=i + Lfr2(k,nfr)=j + else + nfr=nfr+1 + j=1 + ifr2(k,nfr,j)=i + Lfr2(k,nfr)=j + endif + enddo + Lfr_max=0 + i_fr2(k)=1 !ID of the maximum piece + do i=1,nfr + if(Lfr_max.lt.Lfr2(k,i))then + Lfr_max=Lfr2(k,i) + i_fr2(k)=i + endif + enddo + if(Lfr_max.lt.r_min)then + dcu=1.1*dcu + goto 20 + endif + enddo +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ccc select what piece will be used (this may araise ansysmetry, but +ccc only when L1=L2 and Lfr1=Lfr2 and L1 ne Lfr1 +ccc if L1=Lfr1 and L2=Lfr2 (normal proteins), it will be the same as initial1 + mark=1 + if(Lfr2(1,i_fr2(1)).lt.Lfr2(2,i_fr2(2)))then + mark=1 + elseif(Lfr2(1,i_fr2(1)).gt.Lfr2(2,i_fr2(2)))then + mark=2 + else !Lfr1=Lfr2 + if(nseq1.le.nseq2)then + mark=1 + else + mark=2 + endif + endif +ccc + L_fr=Lfr2(mark,i_fr2(mark)) + do i=1,L_fr + ifr(i)=ifr2(mark,i_fr2(mark),i) + enddo +ccc + if(mark.eq.1)then !non-redundant to get_initial1 + nseq0=nseq1 + else + nseq0=nseq2 + endif + if(L_fr.eq.nseq0)then + n1=int(nseq0*0.1) !0 + n2=int(nseq0*0.89) !2 + j=0 + do i=n1,n2 + j=j+1 + ifr(j)=ifr(n1+j) + enddo + L_fr=j + endif + +ccc get initial -------------> + if(mark.eq.1)then !nseq1 as the smallest one + nseq1_=L_fr + aL=min(nseq1_,nseq2) + idel=aL/2.5 !minimum size of considered fragment + if(idel.le.fra_min1)idel=fra_min1 + n1=-nseq2+idel !shift1 + n2=nseq1_-idel !shift2 + GL_max=0 + do ishift=n1,n2 + L=0 + do j=1,nseq2 + i=j+ishift + if(i.ge.1.and.i.le.nseq1_)then + L=L+1 + invmap(j)=ifr(i) + else + invmap(j)=-1 + endif + enddo + if(L.ge.idel)then + call get_GL(GL) + if(GL.gt.GL_max)then + GL_max=GL + do i=1,nseq2 + invmap_i(i)=invmap(i) + enddo + endif + endif + enddo + else + nseq2_=L_fr + aL=min(nseq1,nseq2_) + idel=aL/2.5 !minimum size of considered fragment + if(idel.le.fra_min1)idel=fra_min1 + n1=-nseq2_+idel + n2=nseq1-idel + GL_max=0 + do ishift=n1,n2 + L=0 + do j=1,nseq2 + invmap(j)=-1 + enddo + do j=1,nseq2_ + i=j+ishift + if(i.ge.1.and.i.le.nseq1)then + L=L+1 + invmap(ifr(j))=i + endif + enddo + if(L.ge.idel)then + call get_GL(GL) + if(GL.gt.GL_max)then + GL_max=GL + do i=1,nseq2 + invmap_i(i)=invmap(i) + enddo + endif + endif + enddo + endif + + return + end + +************************************************************** +* fifth initial alignement. Using local structure super * +* position. * +************************************************************** + subroutine get_initial5 + PARAMETER (nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + common/length/nseq1,nseq2 + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/alignrst/invmap0(nmax) + common/zscore/zrms,n_al,rmsd_al + common/TM/TM,TMmax + common/d0/d0,anseq + common/d0min/d0_min + common/init/invmap_i(nmax) + common/initial4/mm1(nmax),mm2(nmax) + common/tinit/invmap_ii(nmax) + common/sec/isec(nmax),jsec(nmax) + logical contin + integer n_all,secmatch,coilcnt + real n_max_cut,n_all_max,n_cutt + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms + data w /nmax*1.0/ + common/inv/invmap_a(nmax) + common/speed/align_len1 + integer aL,aLL,m1,m2,n_frag,n_frag1,n_frag2,rem +***** setting parameters ************************************ + m1=0 + m2=0 + n_frag=20 + if(nseq1.gt.250.and.nseq2.gt.250)then + n_frag=50 + goto 100 + elseif(nseq1.gt.200.and.nseq2.gt.200)then + n_frag=40 + goto 100 + elseif(nseq1.gt.150.and.nseq2.gt.150)then + n_frag=30 + goto 100 + !elseif(nseq1.lt.100.and.nseq2.lt.100)then + ! n_frag=15 + ! goto 100 + !elseif(nseq1.lt.200.and.nseq2.gt.200)then + ! n_frag=22 + ! goto 100 + !elseif(nseq1.gt.150.and.nseq2.gt.150)then + ! n_frag=20 + ! goto 100 + !elseif(nseq1.gt.150.and.nseq2.lt.150)then + ! n_frag=18 + ! goto 100 + !elseif(nseq1.lt.150.and.nseq2.gt.150)then + ! n_frag=18 + ! goto 100 + ! + !elseif(nseq1.gt.100.and.nseq2.gt.100)then + ! n_frag=16 + ! goto 100 + !elseif(nseq1.gt.100.and.nseq2.lt.100)then + ! n_frag=14 + ! goto 100 + !elseif(nseq1.lt.100.and.nseq2.lt.100)then + ! n_frag=14 + ! goto 100 + !else + ! n_frag=12 + endif + + 100 continue + + + n_jump=n_frag + !n_all=0 + !n_all_max=0 + !n_max_cut=0.7 + !n_cutt=0 + d01=d0+1.5 + if(d01.lt.d0_min)d01=d0_min + d02=d01*d01 + !GLmaxB=0 + GLmaxA=0 + GL=0 + !GLmaxA_cut=0.12 + !n_frag1=n_frag-1 + !n_frag2=n_frag/2 + + + m1=nseq1-n_frag-20 + m2=nseq2-n_frag-20 + + do ii=20,m1,n_jump + do jj=20,m2,n_jump + + do k=1,n_frag + iii=ii+k-1 + jjj=jj+k-1 + r_1(1,k)=xa(1,iii,0) + r_1(2,k)=xa(2,iii,0) + r_1(3,k)=xa(3,iii,0) + r_2(1,k)=xa(1,jjj,1) + r_2(2,k)=xa(2,jjj,1) + r_2(3,k)=xa(3,jjj,1) + enddo + +*********superpose the two structures and rotate it ***************** + call u3b(w,r_1,r_2,n_frag,1,rms,u,t,ier) !u rotate r_1 to r_2 + + + do i1=1,nseq1 + xx=t(1)+u(1,1)*xa(1,i1,0)+u(1,2)*xa(2,i1,0)+u(1,3) + & *xa(3,i1,0) + yy=t(2)+u(2,1)*xa(1,i1,0)+u(2,2)*xa(2,i1,0)+u(2,3) + & *xa(3,i1,0) + zz=t(3)+u(3,1)*xa(1,i1,0)+u(3,2)*xa(2,i1,0)+u(3,3) + & *xa(3,i1,0) + do j1=1,nseq2 + dd=(xx-xa(1,j1,1))**2+(yy-xa(2,j1,1))**2+ + & (zz-xa(3,j1,1))**2 + score(i1,j1)=1/(1+dd/d02) ! changing + enddo + enddo + + +*********extract alignement with score(i,j) ***************** + !align_len1=0 + call DP(NSEQ1,NSEQ2) + + + call get_GL(GL) + + if(GL.gt.GLmaxA)then + GLmaxA=GL + do j1=1,nseq2 + invmap_i(j1)=invmap(j1) + enddo + endif + + enddo + + enddo + + return + end + + + + +************************************************************** +* smooth the secondary structure assignment +************************************************************** + subroutine smooth + PARAMETER(nmax=5000) + common/sec/isec(nmax),jsec(nmax) + common/length/nseq1,nseq2 + +*** smooth single --------------> +*** --x-- => ----- + do i=1,nseq1 + if(isec(i).eq.2.or.isec(i).eq.4)then + j=isec(i) + if(isec(i-2).ne.j)then + if(isec(i-1).ne.j)then + if(isec(i+1).ne.j)then + if(isec(i+1).ne.j)then + isec(i)=1 + endif + endif + endif + endif + endif + enddo + do i=1,nseq2 + if(jsec(i).eq.2.or.jsec(i).eq.4)then + j=jsec(i) + if(jsec(i-2).ne.j)then + if(jsec(i-1).ne.j)then + if(jsec(i+1).ne.j)then + if(jsec(i+1).ne.j)then + jsec(i)=1 + endif + endif + endif + endif + endif + enddo + +*** smooth double --------------> +*** --xx-- => ------ + do i=1,nseq1 + if(isec(i).ne.2)then + if(isec(i+1).ne.2)then + if(isec(i+2).eq.2)then + if(isec(i+3).eq.2)then + if(isec(i+4).ne.2)then + if(isec(i+5).ne.2)then + isec(i+2)=1 + isec(i+3)=1 + endif + endif + endif + endif + endif + endif + + if(isec(i).ne.4)then + if(isec(i+1).ne.4)then + if(isec(i+2).eq.4)then + if(isec(i+3).eq.4)then + if(isec(i+4).ne.4)then + if(isec(i+5).ne.4)then + isec(i+2)=1 + isec(i+3)=1 + endif + endif + endif + endif + endif + endif + enddo + do i=1,nseq2 + if(jsec(i).ne.2)then + if(jsec(i+1).ne.2)then + if(jsec(i+2).eq.2)then + if(jsec(i+3).eq.2)then + if(jsec(i+4).ne.2)then + if(jsec(i+5).ne.2)then + jsec(i+2)=1 + jsec(i+3)=1 + endif + endif + endif + endif + endif + endif + + if(jsec(i).ne.4)then + if(jsec(i+1).ne.4)then + if(jsec(i+2).eq.4)then + if(jsec(i+3).eq.4)then + if(jsec(i+4).ne.4)then + if(jsec(i+5).ne.4)then + jsec(i+2)=1 + jsec(i+3)=1 + endif + endif + endif + endif + endif + endif + enddo + +*** connect --------------> +*** x-x => xxx + do i=1,nseq1 + if(isec(i).eq.2)then + if(isec(i+1).ne.2)then + if(isec(i+2).eq.2)then + isec(i+1)=2 + endif + endif + endif + + if(isec(i).eq.4)then + if(isec(i+1).ne.4)then + if(isec(i+2).eq.4)then + isec(i+1)=4 + endif + endif + endif + enddo + do i=1,nseq2 + if(jsec(i).eq.2)then + if(jsec(i+1).ne.2)then + if(jsec(i+2).eq.2)then + jsec(i+1)=2 + endif + endif + endif + + if(jsec(i).eq.4)then + if(jsec(i+1).ne.4)then + if(jsec(i+2).eq.4)then + jsec(i+1)=4 + endif + endif + endif + enddo + + return + end + +************************************************************* +* assign secondary structure: +************************************************************* + function diszy(i,i1,i2) + PARAMETER(nmax=5000) + COMMON/BACKBONE/XA(3,nmax,0:1) + diszy=sqrt((xa(1,i1,i)-xa(1,i2,i))**2 + & +(xa(2,i1,i)-xa(2,i2,i))**2 + & +(xa(3,i1,i)-xa(3,i2,i))**2) + return + end + +************************************************************* +* assign secondary structure: +************************************************************* + function make_sec(dis13,dis14,dis15,dis24,dis25,dis35) + make_sec=1 + delta=2.1 + if(abs(dis15-6.37).lt.delta)then + if(abs(dis14-5.18).lt.delta)then + if(abs(dis25-5.18).lt.delta)then + if(abs(dis13-5.45).lt.delta)then + if(abs(dis24-5.45).lt.delta)then + if(abs(dis35-5.45).lt.delta)then + make_sec=2 !helix + return + endif + endif + endif + endif + endif + endif + delta=1.42 + if(abs(dis15-13).lt.delta)then + if(abs(dis14-10.4).lt.delta)then + if(abs(dis25-10.4).lt.delta)then + if(abs(dis13-6.1).lt.delta)then + if(abs(dis24-6.1).lt.delta)then + if(abs(dis35-6.1).lt.delta)then + make_sec=4 !strand + return + endif + endif + endif + endif + endif + endif + if(dis15.lt.8)then + make_sec=3 + endif + + return + end + +**************************************************************** +* quickly calculate TM-score with given invmap(i) in 3 iterations +**************************************************************** + subroutine get_GL(GL) + PARAMETER(nmax=5000) + common/length/nseq1,nseq2 + COMMON/BACKBONE/XA(3,nmax,0:1) + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/zscore/zrms,n_al,rmsd_al + common/d0/d0,anseq + dimension xtm1(nmax),ytm1(nmax),ztm1(nmax) + dimension xtm2(nmax),ytm2(nmax),ztm2(nmax) + common/TM/TM,TMmax + common/n1n2/n1(nmax),n2(nmax) + common/d00/d00,d002 + + dimension xo1(nmax),yo1(nmax),zo1(nmax) + dimension xo2(nmax),yo2(nmax),zo2(nmax) + dimension dis2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +c calculate RMSD between aligned structures and rotate the structures --> + n_al=0 + do j=1,NSEQ2 + i=invmap(j) !j aligned to i + if(i.gt.0)then + n_al=n_al+1 + r_1(1,n_al)=xa(1,i,0) + r_1(2,n_al)=xa(2,i,0) + r_1(3,n_al)=xa(3,i,0) + r_2(1,n_al)=xa(1,j,1) + r_2(2,n_al)=xa(2,j,1) + r_2(3,n_al)=xa(3,j,1) + xo1(n_al)=xa(1,i,0) + yo1(n_al)=xa(2,i,0) + zo1(n_al)=xa(3,i,0) + xo2(n_al)=xa(1,j,1) + yo2(n_al)=xa(2,j,1) + zo2(n_al)=xa(3,j,1) + endif + enddo + call u3b(w,r_1,r_2,n_al,1,rms,u,t,ier) !u rotate r_1 to r_2 + GL=0 + do i=1,n_al + xx=t(1)+u(1,1)*xo1(i)+u(1,2)*yo1(i)+u(1,3)*zo1(i) + yy=t(2)+u(2,1)*xo1(i)+u(2,2)*yo1(i)+u(2,3)*zo1(i) + zz=t(3)+u(3,1)*xo1(i)+u(3,2)*yo1(i)+u(3,3)*zo1(i) + dis2(i)=(xx-xo2(i))**2+(yy-yo2(i))**2+(zz-zo2(i))**2 + GL=GL+1/(1+dis2(i)/(d0**2)) + enddo +ccc for next iteration-------------> + d002t=d002 + 21 j=0 + do i=1,n_al + if(dis2(i).le.d002t)then + j=j+1 + r_1(1,j)=xo1(i) + r_1(2,j)=yo1(i) + r_1(3,j)=zo1(i) + r_2(1,j)=xo2(i) + r_2(2,j)=yo2(i) + r_2(3,j)=zo2(i) + endif + enddo + if(j.lt.3.and.n_al.gt.3)then + d002t=d002t+.5 + goto 21 + endif + L=j + call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2 + G2=0 + do i=1,n_al + xx=t(1)+u(1,1)*xo1(i)+u(1,2)*yo1(i)+u(1,3)*zo1(i) + yy=t(2)+u(2,1)*xo1(i)+u(2,2)*yo1(i)+u(2,3)*zo1(i) + zz=t(3)+u(3,1)*xo1(i)+u(3,2)*yo1(i)+u(3,3)*zo1(i) + dis2(i)=(xx-xo2(i))**2+(yy-yo2(i))**2+(zz-zo2(i))**2 + G2=G2+1/(1+dis2(i)/(d0**2)) + enddo +ccc for next iteration-------------> + d002t=d002+1 + 22 j=0 + do i=1,n_al + if(dis2(i).le.d002t)then + j=j+1 + r_1(1,j)=xo1(i) + r_1(2,j)=yo1(i) + r_1(3,j)=zo1(i) + r_2(1,j)=xo2(i) + r_2(2,j)=yo2(i) + r_2(3,j)=zo2(i) + endif + enddo + if(j.lt.3.and.n_al.gt.3)then + d002t=d002t+.5 + goto 22 + endif + L=j + call u3b(w,r_1,r_2,L,1,rms,u,t,ier) !u rotate r_1 to r_2 + G3=0 + do i=1,n_al + xx=t(1)+u(1,1)*xo1(i)+u(1,2)*yo1(i)+u(1,3)*zo1(i) + yy=t(2)+u(2,1)*xo1(i)+u(2,2)*yo1(i)+u(2,3)*zo1(i) + zz=t(3)+u(3,1)*xo1(i)+u(3,2)*yo1(i)+u(3,3)*zo1(i) + dis2(i)=(xx-xo2(i))**2+(yy-yo2(i))**2+(zz-zo2(i))**2 + G3=G3+1/(1+dis2(i)/(d0**2)) + enddo + if(G2.gt.GL)GL=G2 + if(G3.gt.GL)GL=G3 + +c^^^^^^^^^^^^^^^^ GL done ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + end + +**************************************************************** +* with invmap(i) calculate TM-score and martix score(i,j) for rotation +**************************************************************** + subroutine get_score + PARAMETER(nmax=5000) + common/length/nseq1,nseq2 + COMMON/BACKBONE/XA(3,nmax,0:1) + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/zscore/zrms,n_al,rmsd_al + common/d0/d0,anseq + dimension xtm1(nmax),ytm1(nmax),ztm1(nmax) + dimension xtm2(nmax),ytm2(nmax),ztm2(nmax) + common/TM/TM,TMmax + common/n1n2/n1(nmax),n2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +c calculate RMSD between aligned structures and rotate the structures --> + n_al=0 + do j=1,NSEQ2 + i=invmap(j) !j aligned to i + if(i.gt.0)then + n_al=n_al+1 +ccc for TM-score: + xtm1(n_al)=xa(1,i,0) !for TM-score + ytm1(n_al)=xa(2,i,0) + ztm1(n_al)=xa(3,i,0) + xtm2(n_al)=xa(1,j,1) + ytm2(n_al)=xa(2,j,1) + ztm2(n_al)=xa(3,j,1) +ccc for rotation matrix: + r_1(1,n_al)=xa(1,i,0) + r_1(2,n_al)=xa(2,i,0) + r_1(3,n_al)=xa(3,i,0) + endif + enddo +*** calculate TM-score for the given alignment-----------> + d0_input=d0 + call TMscore8_search(d0_input,n_al,xtm1,ytm1,ztm1,n1, + & n_al,xtm2,ytm2,ztm2,n2,TM,Rcomm,Lcomm) !simplified search engine + TM=TM*n_al/anseq !TM-score +*** calculate score matrix score(i,j)------------------> + do i=1,n_al + r_2(1,i)=xtm1(i) + r_2(2,i)=ytm1(i) + r_2(3,i)=ztm1(i) + enddo + call u3b(w,r_1,r_2,n_al,1,rms,u,t,ier) !u rotate r_1 to r_2 + do i=1,nseq1 + xx=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0) + yy=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0) + zz=t(3)+u(3,1)*xa(1,i,0)+u(3,2)*xa(2,i,0)+u(3,3)*xa(3,i,0) + do j=1,nseq2 + dd=(xx-xa(1,j,1))**2+(yy-xa(2,j,1))**2+(zz-xa(3,j,1))**2 + score(i,j)=1/(1+dd/d0**2) + enddo + enddo + +c^^^^^^^^^^^^^^^^ score(i,j) done ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + end + +**************************************************************** +* with invmap(i) calculate score(i,j) using RMSD rotation +**************************************************************** + subroutine get_score1 + PARAMETER(nmax=5000) + common/length/nseq1,nseq2 + COMMON/BACKBONE/XA(3,nmax,0:1) + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + common/zscore/zrms,n_al,rmsd_al + common/d0/d0,anseq + common/d0min/d0_min + dimension xtm1(nmax),ytm1(nmax),ztm1(nmax) + dimension xtm2(nmax),ytm2(nmax),ztm2(nmax) + common/TM/TM,TMmax + common/n1n2/n1(nmax),n2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +c calculate RMSD between aligned structures and rotate the structures --> + n_al=0 + do j=1,NSEQ2 + i=invmap(j) !j aligned to i + if(i.gt.0)then + n_al=n_al+1 +ccc for rotation matrix: + r_1(1,n_al)=xa(1,i,0) + r_1(2,n_al)=xa(2,i,0) + r_1(3,n_al)=xa(3,i,0) + r_2(1,n_al)=xa(1,j,1) + r_2(2,n_al)=xa(2,j,1) + r_2(3,n_al)=xa(3,j,1) + endif + enddo +*** calculate score matrix score(i,j)------------------> + call u3b(w,r_1,r_2,n_al,1,rms,u,t,ier) !u rotate r_1 to r_2 + d01=d0+1.5 + if(d01.lt.d0_min)d01=d0_min + d02=d01*d01 + do i=1,nseq1 + xx=t(1)+u(1,1)*xa(1,i,0)+u(1,2)*xa(2,i,0)+u(1,3)*xa(3,i,0) + yy=t(2)+u(2,1)*xa(1,i,0)+u(2,2)*xa(2,i,0)+u(2,3)*xa(3,i,0) + zz=t(3)+u(3,1)*xa(1,i,0)+u(3,2)*xa(2,i,0)+u(3,3)*xa(3,i,0) + do j=1,nseq2 + dd=(xx-xa(1,j,1))**2+(yy-xa(2,j,1))**2+(zz-xa(3,j,1))**2 + score(i,j)=1/(1+dd/d02) + enddo + enddo + +c^^^^^^^^^^^^^^^^ score(i,j) done ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + end + + +************************************************************************* +************************************************************************* +* This is a subroutine to compare two structures and find the +* superposition that has the maximum TM-score. +* +* L1--Length of the first structure +* (x1(i),y1(i),z1(i))--coordinates of i'th residue at the first structure +* n1(i)--Residue sequence number of i'th residue at the first structure +* L2--Length of the second structure +* (x2(i),y2(i),z2(i))--coordinates of i'th residue at the second structure +* n2(i)--Residue sequence number of i'th residue at the second structure +* TM--TM-score of the comparison +* Rcomm--RMSD of two structures in the common aligned residues +* Lcomm--Length of the common aligned regions +* +* Note: +* 1, Always put native as the second structure, by which TM-score +* is normalized. +* 2, The returned (x1(i),y1(i),z1(i)) are the rotated structure after +* TM-score superposition. +************************************************************************* +************************************************************************* +*** dis<8, simplified search engine + subroutine TMscore8_search(dx,L1,x1,y1,z1,n1,L2,x2,y2,z2,n2, + & TM,Rcomm,Lcomm) + PARAMETER(nmax=5000) + common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0 + common/d0min/d0_min + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + dimension k_ali(nmax),k_ali0(nmax) + dimension L_ini(100),iq(nmax) + common/scores/score + double precision score,score_max + dimension xa(nmax),ya(nmax),za(nmax) + dimension iL0(nmax) + + dimension x1(nmax),y1(nmax),z1(nmax),n1(nmax) + dimension x2(nmax),y2(nmax),z2(nmax),n2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +********* convert input data *************************** +* because L1=L2 in this special case----------> + nseqA=L1 + nseqB=L2 + do i=1,nseqA + xa(i)=x1(i) + ya(i)=y1(i) + za(i)=z1(i) + nresA(i)=n1(i) + xb(i)=x2(i) + yb(i)=y2(i) + zb(i)=z2(i) + nresB(i)=n2(i) + iA(i)=i + iB(i)=i + enddo + n_ali=L1 !number of aligned residues + Lcomm=L1 + +************///// +* parameters: +***************** +*** d0-------------> + d0=dx + if(d0.lt.d0_min)d0=d0_min +*** d0_search -----> + d0_search=d0 + if(d0_search.gt.8)d0_search=8 + if(d0_search.lt.4.5)d0_search=4.5 +*** iterative parameters -----> + + n_it=20 !maximum number of iterations + d_output=5 !for output alignment + n_init_max=6 !maximum number of L_init + n_init=0 + L_ini_min=4 + + if(n_ali.lt.4)L_ini_min=n_ali + do i=1,n_init_max-1 + n_init=n_init+1 + L_ini(n_init)=n_ali/2**(n_init-1) + if(L_ini(n_init).le.L_ini_min)then + L_ini(n_init)=L_ini_min + goto 402 + endif + enddo + n_init=n_init+1 + L_ini(n_init)=L_ini_min + 402 continue + +****************************************************************** +* find the maximum score starting from local structures superposition +****************************************************************** + score_max=-1 !TM-score + do 333 i_init=1,n_init + L_init=L_ini(i_init) + iL_max=n_ali-L_init+1 + k=0 + do i=1,iL_max,40 !this is the simplification! + k=k+1 + iL0(k)=i + enddo + if(iL0(k).lt.iL_max)then + k=k+1 + iL0(k)=iL_max + endif + n_shift=k + do 300 i_shift=1,n_shift + iL=iL0(i_shift) + LL=0 + ka=0 + do i=1,L_init + k=iL+i-1 ![1,n_ali] common aligned + r_1(1,i)=xa(iA(k)) + r_1(2,i)=ya(iA(k)) + r_1(3,i)=za(iA(k)) + r_2(1,i)=xb(iB(k)) + r_2(2,i)=yb(iB(k)) + r_2(3,i)=zb(iB(k)) + LL=LL+1 + ka=ka+1 + k_ali(ka)=k + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + if(i_init.eq.1)then !global superposition + armsd=dsqrt(rms/LL) + Rcomm=armsd + endif + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + d=d0_search-1 + call score_fun8 !init, get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka0 + k_ali0(i)=k_ali(i) + enddo + endif +*** iteration for extending ----------------------------------> + d=d0_search+1 + do 301 it=1,n_it + LL=0 + ka=0 + do i=1,n_cut + m=i_ali(i) ![1,n_ali] + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + ka=ka+1 + k_ali(ka)=m + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + call score_fun8 !get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka + k_ali0(i)=k_ali(i) + enddo + endif + if(it.eq.n_it)goto 302 + if(n_cut.eq.ka)then + neq=0 + do i=1,n_cut + if(i_ali(i).eq.k_ali(i))neq=neq+1 + enddo + if(n_cut.eq.neq)goto 302 + endif + 301 continue !for iteration + 302 continue + 300 continue !for shift + 333 continue !for initial length, L_ali/M + +******** return the final rotation **************** + LL=0 + do i=1,ka0 + m=k_ali0(i) !record of the best alignment + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + x1(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + y1(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + z1(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + TM=score_max + +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + END + +************************************************************************* +************************************************************************* +* This is a subroutine to compare two structures and find the +* superposition that has the maximum TM-score. +* +* L1--Length of the first structure +* (x1(i),y1(i),z1(i))--coordinates of i'th residue at the first structure +* n1(i)--Residue sequence number of i'th residue at the first structure +* L2--Length of the second structure +* (x2(i),y2(i),z2(i))--coordinates of i'th residue at the second structure +* n2(i)--Residue sequence number of i'th residue at the second structure +* TM--TM-score of the comparison +* Rcomm--RMSD of two structures in the common aligned residues +* Lcomm--Length of the common aligned regions +* +* Note: +* 1, Always put native as the second structure, by which TM-score +* is normalized. +* 2, The returned (x1(i),y1(i),z1(i)) are the rotated structure after +* TM-score superposition. +************************************************************************* +************************************************************************* +*** dis<8, but same search engine + subroutine TMscore8(dx,L1,x1,y1,z1,n1,L2,x2,y2,z2,n2, + & TM,Rcomm,Lcomm) + PARAMETER(nmax=5000) + common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0 + common/d0min/d0_min + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + dimension k_ali(nmax),k_ali0(nmax) + dimension L_ini(100),iq(nmax) + common/scores/score + double precision score,score_max + dimension xa(nmax),ya(nmax),za(nmax) + + dimension x1(nmax),y1(nmax),z1(nmax),n1(nmax) + dimension x2(nmax),y2(nmax),z2(nmax),n2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +********* convert input data *************************** +* because L1=L2 in this special case----------> + nseqA=L1 + nseqB=L2 + do i=1,nseqA + xa(i)=x1(i) + ya(i)=y1(i) + za(i)=z1(i) + nresA(i)=n1(i) + xb(i)=x2(i) + yb(i)=y2(i) + zb(i)=z2(i) + nresB(i)=n2(i) + iA(i)=i + iB(i)=i + enddo + n_ali=L1 !number of aligned residues + Lcomm=L1 + +************///// +* parameters: +***************** +*** d0-------------> + d0=dx + if(d0.lt.d0_min)d0=d0_min +*** d0_search -----> + d0_search=d0 + if(d0_search.gt.8)d0_search=8 + if(d0_search.lt.4.5)d0_search=4.5 +*** iterative parameters -----> + n_it=20 !maximum number of iterations + d_output=5 !for output alignment + n_init_max=6 !maximum number of L_init + n_init=0 + L_ini_min=4 + if(n_ali.lt.4)L_ini_min=n_ali + do i=1,n_init_max-1 + n_init=n_init+1 + L_ini(n_init)=n_ali/2**(n_init-1) + if(L_ini(n_init).le.L_ini_min)then + L_ini(n_init)=L_ini_min + goto 402 + endif + enddo + n_init=n_init+1 + L_ini(n_init)=L_ini_min + 402 continue + +****************************************************************** +* find the maximum score starting from local structures superposition +****************************************************************** + score_max=-1 !TM-score + do 333 i_init=1,n_init + L_init=L_ini(i_init) + iL_max=n_ali-L_init+1 + do 300 iL=1,iL_max !on aligned residues, [1,nseqA] + LL=0 + ka=0 + do i=1,L_init + k=iL+i-1 ![1,n_ali] common aligned + r_1(1,i)=xa(iA(k)) + r_1(2,i)=ya(iA(k)) + r_1(3,i)=za(iA(k)) + r_2(1,i)=xb(iB(k)) + r_2(2,i)=yb(iB(k)) + r_2(3,i)=zb(iB(k)) + LL=LL+1 + ka=ka+1 + k_ali(ka)=k + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + if(i_init.eq.1)then !global superposition + armsd=dsqrt(rms/LL) + Rcomm=armsd + endif + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + d=d0_search-1 + call score_fun8 !init, get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka0 + k_ali0(i)=k_ali(i) + enddo + endif +*** iteration for extending ----------------------------------> + d=d0_search+1 + do 301 it=1,n_it + LL=0 + ka=0 + do i=1,n_cut + m=i_ali(i) ![1,n_ali] + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + ka=ka+1 + k_ali(ka)=m + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + call score_fun8 !get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka + k_ali0(i)=k_ali(i) + enddo + endif + if(it.eq.n_it)goto 302 + if(n_cut.eq.ka)then + neq=0 + do i=1,n_cut + if(i_ali(i).eq.k_ali(i))neq=neq+1 + enddo + if(n_cut.eq.neq)goto 302 + endif + 301 continue !for iteration + 302 continue + 300 continue !for shift + 333 continue !for initial length, L_ali/M + +******** return the final rotation **************** + LL=0 + do i=1,ka0 + m=k_ali0(i) !record of the best alignment + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + x1(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + y1(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + z1(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + TM=score_max + +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + END + +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c 1, collect those residues with dis<d; +c 2, calculate score_GDT, score_maxsub, score_TM +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + subroutine score_fun8 + PARAMETER(nmax=5000) + + common/stru/xa(nmax),ya(nmax),za(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0 + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + common/scores/score + double precision score,score_max + common/d8/d8 + + d_tmp=d + 21 n_cut=0 !number of residue-pairs dis<d, for iteration + score_sum=0 !TMscore + do k=1,n_ali + i=iA(k) ![1,nseqA] reoder number of structureA + j=iB(k) ![1,nseqB] + dis=sqrt((xa(i)-xb(j))**2+(ya(i)-yb(j))**2+(za(i)-zb(j))**2) + if(dis.lt.d_tmp)then + n_cut=n_cut+1 + i_ali(n_cut)=k ![1,n_ali], mark the residue-pairs in dis<d + endif + if(dis.le.d8)then + score_sum=score_sum+1/(1+(dis/d0)**2) + endif + enddo + if(n_cut.lt.3.and.n_ali.gt.3)then + d_tmp=d_tmp+.5 + goto 21 + endif + score=score_sum/float(nseqB) !TM-score + + return + end + +************************************************************************* +************************************************************************* +* This is a subroutine to compare two structures and find the +* superposition that has the maximum TM-score. +* +* L1--Length of the first structure +* (x1(i),y1(i),z1(i))--coordinates of i'th residue at the first structure +* n1(i)--Residue sequence number of i'th residue at the first structure +* L2--Length of the second structure +* (x2(i),y2(i),z2(i))--coordinates of i'th residue at the second structure +* n2(i)--Residue sequence number of i'th residue at the second structure +* TM--TM-score of the comparison +* Rcomm--RMSD of two structures in the common aligned residues +* Lcomm--Length of the common aligned regions +* +* Note: +* 1, Always put native as the second structure, by which TM-score +* is normalized. +* 2, The returned (x1(i),y1(i),z1(i)) are the rotated structure after +* TM-score superposition. +************************************************************************* +************************************************************************* +*** normal TM-score: + subroutine TMscore(dx,L1,x1,y1,z1,n1,L2,x2,y2,z2,n2, + & TM,Rcomm,Lcomm) + PARAMETER(nmax=5000) + common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0 + common/d0min/d0_min + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + dimension k_ali(nmax),k_ali0(nmax) + dimension L_ini(100),iq(nmax) + common/scores/score + double precision score,score_max + dimension xa(nmax),ya(nmax),za(nmax) + + dimension x1(nmax),y1(nmax),z1(nmax),n1(nmax) + dimension x2(nmax),y2(nmax),z2(nmax),n2(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + +********* convert input data *************************** +* because L1=L2 in this special case----------> + nseqA=L1 + nseqB=L2 + do i=1,nseqA + xa(i)=x1(i) + ya(i)=y1(i) + za(i)=z1(i) + nresA(i)=n1(i) + xb(i)=x2(i) + yb(i)=y2(i) + zb(i)=z2(i) + nresB(i)=n2(i) + iA(i)=i + iB(i)=i + enddo + n_ali=L1 !number of aligned residues + Lcomm=L1 + +************///// +* parameters: +***************** +*** d0-------------> +c d0=1.24*(nseqB-15)**(1.0/3.0)-1.8 + d0=dx + if(d0.lt.d0_min)d0=d0_min +*** d0_search -----> + d0_search=d0 + if(d0_search.gt.8)d0_search=8 + if(d0_search.lt.4.5)d0_search=4.5 +*** iterative parameters -----> + n_it=20 !maximum number of iterations + d_output=5 !for output alignment + n_init_max=6 !maximum number of L_init + n_init=0 + L_ini_min=4 + if(n_ali.lt.4)L_ini_min=n_ali + do i=1,n_init_max-1 + n_init=n_init+1 + L_ini(n_init)=n_ali/2**(n_init-1) + if(L_ini(n_init).le.L_ini_min)then + L_ini(n_init)=L_ini_min + goto 402 + endif + enddo + n_init=n_init+1 + L_ini(n_init)=L_ini_min + 402 continue + +****************************************************************** +* find the maximum score starting from local structures superposition +****************************************************************** + score_max=-1 !TM-score + do 333 i_init=1,n_init + L_init=L_ini(i_init) + iL_max=n_ali-L_init+1 + do 300 iL=1,iL_max !on aligned residues, [1,nseqA] + LL=0 + ka=0 + do i=1,L_init + k=iL+i-1 ![1,n_ali] common aligned + r_1(1,i)=xa(iA(k)) + r_1(2,i)=ya(iA(k)) + r_1(3,i)=za(iA(k)) + r_2(1,i)=xb(iB(k)) + r_2(2,i)=yb(iB(k)) + r_2(3,i)=zb(iB(k)) + LL=LL+1 + ka=ka+1 + k_ali(ka)=k + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + if(i_init.eq.1)then !global superposition + armsd=dsqrt(rms/LL) + Rcomm=armsd + endif + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + d=d0_search-1 + call score_fun !init, get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka0 + k_ali0(i)=k_ali(i) + enddo + endif +*** iteration for extending ----------------------------------> + d=d0_search+1 + do 301 it=1,n_it + LL=0 + ka=0 + do i=1,n_cut + m=i_ali(i) ![1,n_ali] + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + ka=ka+1 + k_ali(ka)=m + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + call score_fun !get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka + k_ali0(i)=k_ali(i) + enddo + endif + if(it.eq.n_it)goto 302 + if(n_cut.eq.ka)then + neq=0 + do i=1,n_cut + if(i_ali(i).eq.k_ali(i))neq=neq+1 + enddo + if(n_cut.eq.neq)goto 302 + endif + 301 continue !for iteration + 302 continue + 300 continue !for shift + 333 continue !for initial length, L_ali/M + +******** return the final rotation **************** + LL=0 + do i=1,ka0 + m=k_ali0(i) !record of the best alignment + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + x1(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + y1(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + z1(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + TM=score_max + +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + return + END + +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c 1, collect those residues with dis<d; +c 2, calculate score_GDT, score_maxsub, score_TM +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + subroutine score_fun + PARAMETER(nmax=5000) + + common/stru/xa(nmax),ya(nmax),za(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0 + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + common/scores/score + double precision score + + d_tmp=d + 21 n_cut=0 !number of residue-pairs dis<d, for iteration + score_sum=0 !TMscore + do k=1,n_ali + i=iA(k) ![1,nseqA] reoder number of structureA + j=iB(k) ![1,nseqB] + dis=sqrt((xa(i)-xb(j))**2+(ya(i)-yb(j))**2+(za(i)-zb(j))**2) + if(dis.lt.d_tmp)then + n_cut=n_cut+1 + i_ali(n_cut)=k ![1,n_ali], mark the residue-pairs in dis<d + endif + score_sum=score_sum+1/(1+(dis/d0)**2) + enddo + if(n_cut.lt.3.and.n_ali.gt.3)then + d_tmp=d_tmp+.5 + goto 21 + endif + score=score_sum/float(nseqB) !TM-score + + return + end + +******************************************************************** +* Dynamic programming for alignment. +* Input: score(i,j), and gap_open +* Output: invmap(j) +* +* Please note this subroutine is not a correct implementation of +* the N-W dynamic programming because the score tracks back only +* one layer of the matrix. This code was exploited in TM-align +* because it is about 1.5 times faster than a complete N-W code +* and does not influence much the final structure alignment result. +******************************************************************** + SUBROUTINE DP(NSEQ1,NSEQ2) + PARAMETER(nmax=5000) + LOGICAL*1 DIR + common/dpc/score(nmax,nmax),gap_open,invmap(nmax) + dimension DIR(0:nmax,0:nmax),VAL(0:nmax,0:nmax) + common/speed/align_len1 + REAL H,V + align_len1=0 +*** initialize the matrix: + val(0,0)=0 + do i=1,nseq1 + dir(i,0)=.false. + val(i,0)=0 + enddo + do j=1,nseq2 + dir(0,j)=.false. + val(0,j)=0 + invmap(j)=-1 + enddo + +*** decide matrix and path: + DO j=1,NSEQ2 + DO i=1,NSEQ1 + D=VAL(i-1,j-1)+SCORE(i,j) + H=VAL(i-1,j) + if(DIR(i-1,j))H=H+GAP_OPEN + V=VAL(i,j-1) + if(DIR(i,j-1))V=V+GAP_OPEN + + IF((D.GE.H).AND.(D.GE.V)) THEN + DIR(I,J)=.true. + VAL(i,j)=D + ELSE + DIR(I,J)=.false. + if(V.GE.H)then + val(i,j)=v + else + val(i,j)=h + end if + ENDIF + ENDDO + ENDDO + +*** extract the alignment: + i=NSEQ1 + j=NSEQ2 + DO WHILE((i.GT.0).AND.(j.GT.0)) + IF(DIR(i,j))THEN + invmap(j)=i + align_len1=align_len1+1 + i=i-1 + j=j-1 + ELSE + H=VAL(i-1,j) + if(DIR(i-1,j))H=H+GAP_OPEN + V=VAL(i,j-1) + if(DIR(i,j-1))V=V+GAP_OPEN + IF(V.GE.H) THEN + j=j-1 + ELSE + i=i-1 + ENDIF + ENDIF + ENDDO + +c^^^^^^^^^^^^^^^Dynamical programming done ^^^^^^^^^^^^^^^^^^^ + return + END + +cccccccccccccccc Calculate sum of (r_d-r_m)^2 cccccccccccccccccccccccccc +c w - w(m) is weight for atom pair c m (given) +c x - x(i,m) are coordinates of atom c m in set x (given) +c y - y(i,m) are coordinates of atom c m in set y (given) +c n - n is number of atom pairs (given) +c mode - 0:calculate rms only (given) +c 1:calculate rms,u,t (takes longer) +c rms - sum of w*(ux+t-y)**2 over all atom pairs (result) +c u - u(i,j) is rotation matrix for best superposition (result) +c t - t(i) is translation vector for best superposition (result) +c ier - 0: a unique optimal superposition has been determined(result) +c -1: superposition is not unique but optimal +c -2: no result obtained because of negative weights w +c or all weights equal to zero. +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + subroutine u3b(w, x, y, n, mode, rms, u, t, ier) + integer ip(9), ip2312(4), i, j, k, l, m1, m, ier, n, mode + double precision w(1), x(3, 1), y(3, 1), u(3, 3), t(3), rms, sigma + double precision r(3, 3), xc(3), yc(3), wc, a(3, 3), b(3, 3), e0, + &e(3), e1, e2, e3, d, spur, det, cof, h, g, cth, sth, sqrth, p, tol + &, rr(6), rr1, rr2, rr3, rr4, rr5, rr6, ss(6), ss1, ss2, ss3, ss4, + &ss5, ss6, zero, one, two, three, sqrt3 + equivalence (rr(1), rr1), (rr(2), rr2), (rr(3), rr3), (rr(4), rr4) + &, (rr(5), rr5), (rr(6), rr6), (ss(1), ss1), (ss(2), ss2), (ss(3), + &ss3), (ss(4), ss4), (ss(5), ss5), (ss(6), ss6), (e(1), e1), (e(2) + &, e2), (e(3), e3) + data sqrt3 / 1.73205080756888d+00 / + data tol / 1.0d-2 / + data zero / 0.0d+00 / + data one / 1.0d+00 / + data two / 2.0d+00 / + data three / 3.0d+00 / + data ip / 1, 2, 4, 2, 3, 5, 4, 5, 6 / + data ip2312 / 2, 3, 1, 2 / + + +c 156 "rms.for" + wc = zero + rms = 0.0 + e0 = zero + do 1 i = 1, 3 + xc(i) = zero + yc(i) = zero + t(i) = 0.0 + do 1 j = 1, 3 + d = zero + if (i .eq. j) d = one + u(i,j) = d + a(i,j) = d + 1 r(i,j) = zero + ier = -1 +c**** DETERMINE CENTROIDS OF BOTH VECTOR SETS X AND Y +c 170 "rms.for" + if (n .lt. 1) return +c 172 "rms.for" + ier = -2 + do 2 m = 1, n + if (w(m) .lt. 0.0) return + wc = wc + w(m) + do 2 i = 1, 3 + xc(i) = xc(i) + (w(m) * x(i,m)) + 2 yc(i) = yc(i) + (w(m) * y(i,m)) + if (wc .le. zero) return + do 3 i = 1, 3 + xc(i) = xc(i) / wc +c**** DETERMINE CORRELATION MATRIX R BETWEEN VECTOR SETS Y AND X +c 182 "rms.for" + 3 yc(i) = yc(i) / wc +c 184 "rms.for" + do 4 m = 1, n + do 4 i = 1, 3 + e0 = e0 + (w(m) * (((x(i,m) - xc(i)) ** 2) + ((y(i,m) - yc(i)) ** + &2))) +c 187 "rms.for" + d = w(m) * (y(i,m) - yc(i)) + do 4 j = 1, 3 +c**** CALCULATE DETERMINANT OF R(I,J) +c 189 "rms.for" + 4 r(i,j) = r(i,j) + (d * (x(j,m) - xc(j))) +c 191 "rms.for" + det = ((r(1,1) * ((r(2,2) * r(3,3)) - (r(2,3) * r(3,2)))) - (r(1,2 + &) * ((r(2,1) * r(3,3)) - (r(2,3) * r(3,1))))) + (r(1,3) * ((r(2,1) + & * r(3,2)) - (r(2,2) * r(3,1)))) +c**** FORM UPPER TRIANGLE OF TRANSPOSED(R)*R +c 194 "rms.for" + sigma = det +c 196 "rms.for" + m = 0 + do 5 j = 1, 3 + do 5 i = 1, j + m = m + 1 +c***************** EIGENVALUES ***************************************** +c**** FORM CHARACTERISTIC CUBIC X**3-3*SPUR*X**2+3*COF*X-DET=0 +c 200 "rms.for" + 5 rr(m) = ((r(1,i) * r(1,j)) + (r(2,i) * r(2,j))) + (r(3,i) * r(3,j) + &) +c 203 "rms.for" + spur = ((rr1 + rr3) + rr6) / three + cof = ((((((rr3 * rr6) - (rr5 * rr5)) + (rr1 * rr6)) - (rr4 * rr4) + &) + (rr1 * rr3)) - (rr2 * rr2)) / three +c 205 "rms.for" + det = det * det + do 6 i = 1, 3 + 6 e(i) = spur +c**** REDUCE CUBIC TO STANDARD FORM Y**3-3HY+2G=0 BY PUTTING X=Y+SPUR +c 208 "rms.for" + if (spur .le. zero) goto 40 +c 210 "rms.for" + d = spur * spur + h = d - cof +c**** SOLVE CUBIC. ROOTS ARE E1,E2,E3 IN DECREASING ORDER +c 212 "rms.for" + g = (((spur * cof) - det) / two) - (spur * h) +c 214 "rms.for" + if (h .le. zero) goto 8 + sqrth = dsqrt(h) + d = ((h * h) * h) - (g * g) + if (d .lt. zero) d = zero + d = datan2(dsqrt(d),- g) / three + cth = sqrth * dcos(d) + sth = (sqrth * sqrt3) * dsin(d) + e1 = (spur + cth) + cth + e2 = (spur - cth) + sth + e3 = (spur - cth) - sth +c.....HANDLE SPECIAL CASE OF 3 IDENTICAL ROOTS +c 224 "rms.for" + if (mode) 10, 50, 10 +c**************** EIGENVECTORS ***************************************** +c 226 "rms.for" + 8 if (mode) 30, 50, 30 +c 228 "rms.for" + 10 do 15 l = 1, 3, 2 + d = e(l) + ss1 = ((d - rr3) * (d - rr6)) - (rr5 * rr5) + ss2 = ((d - rr6) * rr2) + (rr4 * rr5) + ss3 = ((d - rr1) * (d - rr6)) - (rr4 * rr4) + ss4 = ((d - rr3) * rr4) + (rr2 * rr5) + ss5 = ((d - rr1) * rr5) + (rr2 * rr4) + ss6 = ((d - rr1) * (d - rr3)) - (rr2 * rr2) + j = 1 + if (dabs(ss1) .ge. dabs(ss3)) goto 12 + j = 2 + if (dabs(ss3) .ge. dabs(ss6)) goto 13 + 11 j = 3 + goto 13 + 12 if (dabs(ss1) .lt. dabs(ss6)) goto 11 + 13 d = zero + j = 3 * (j - 1) + do 14 i = 1, 3 + k = ip(i + j) + a(i,l) = ss(k) + 14 d = d + (ss(k) * ss(k)) + if (d .gt. zero) d = one / dsqrt(d) + do 15 i = 1, 3 + 15 a(i,l) = a(i,l) * d + d = ((a(1,1) * a(1,3)) + (a(2,1) * a(2,3))) + (a(3,1) * a(3,3)) + m1 = 3 + m = 1 + if ((e1 - e2) .gt. (e2 - e3)) goto 16 + m1 = 1 + m = 3 + 16 p = zero + do 17 i = 1, 3 + a(i,m1) = a(i,m1) - (d * a(i,m)) + 17 p = p + (a(i,m1) ** 2) + if (p .le. tol) goto 19 + p = one / dsqrt(p) + do 18 i = 1, 3 + 18 a(i,m1) = a(i,m1) * p + goto 21 + 19 p = one + do 20 i = 1, 3 + if (p .lt. dabs(a(i,m))) goto 20 + p = dabs(a(i,m)) + j = i + 20 continue + k = ip2312(j) + l = ip2312(j + 1) + p = dsqrt((a(k,m) ** 2) + (a(l,m) ** 2)) + if (p .le. tol) goto 40 + a(j,m1) = zero + a(k,m1) = - (a(l,m) / p) + a(l,m1) = a(k,m) / p + 21 a(1,2) = (a(2,3) * a(3,1)) - (a(2,1) * a(3,3)) + a(2,2) = (a(3,3) * a(1,1)) - (a(3,1) * a(1,3)) +c****************** ROTATION MATRIX ************************************ +c 282 "rms.for" + a(3,2) = (a(1,3) * a(2,1)) - (a(1,1) * a(2,3)) +c 284 "rms.for" + 30 do 32 l = 1, 2 + d = zero + do 31 i = 1, 3 + b(i,l) = ((r(i,1) * a(1,l)) + (r(i,2) * a(2,l))) + (r(i,3) * a(3,l + &)) +c 288 "rms.for" + 31 d = d + (b(i,l) ** 2) + if (d .gt. zero) d = one / dsqrt(d) + do 32 i = 1, 3 + 32 b(i,l) = b(i,l) * d + d = ((b(1,1) * b(1,2)) + (b(2,1) * b(2,2))) + (b(3,1) * b(3,2)) + p = zero + do 33 i = 1, 3 + b(i,2) = b(i,2) - (d * b(i,1)) + 33 p = p + (b(i,2) ** 2) + if (p .le. tol) goto 35 + p = one / dsqrt(p) + do 34 i = 1, 3 + 34 b(i,2) = b(i,2) * p + goto 37 + 35 p = one + do 36 i = 1, 3 + if (p .lt. dabs(b(i,1))) goto 36 + p = dabs(b(i,1)) + j = i + 36 continue + k = ip2312(j) + l = ip2312(j + 1) + p = dsqrt((b(k,1) ** 2) + (b(l,1) ** 2)) + if (p .le. tol) goto 40 + b(j,2) = zero + b(k,2) = - (b(l,1) / p) + b(l,2) = b(k,1) / p + 37 b(1,3) = (b(2,1) * b(3,2)) - (b(2,2) * b(3,1)) + b(2,3) = (b(3,1) * b(1,2)) - (b(3,2) * b(1,1)) + b(3,3) = (b(1,1) * b(2,2)) - (b(1,2) * b(2,1)) + do 39 i = 1, 3 + do 39 j = 1, 3 +c****************** TRANSLATION VECTOR ********************************* +c 320 "rms.for" + 39 u(i,j) = ((b(i,1) * a(j,1)) + (b(i,2) * a(j,2))) + (b(i,3) * a(j,3 + &)) + 40 do 41 i = 1, 3 +c********************** RMS ERROR ************************************** +c 323 "rms.for" + 41 t(i) = ((yc(i) - (u(i,1) * xc(1))) - (u(i,2) * xc(2))) - (u(i,3) + & * xc(3)) + 50 do 51 i = 1, 3 + if (e(i) .lt. zero) e(i) = zero + 51 e(i) = dsqrt(e(i)) + ier = 0 + if (e2 .le. (e1 * 1.0d-05)) ier = -1 + d = e3 + if (sigma .ge. 0.0) goto 52 + d = - d + if ((e2 - e3) .le. (e1 * 1.0d-05)) ier = -1 + 52 d = (d + e2) + e1 + rms = (e0 - d) - d + if (rms .lt. 0.0) rms = 0.0 + + return +c.....END U3B........................................................... +c---------------------------------------------------------- +c THE END +c---------------------------------------------------------- +c 338 "rms.for" + end diff --git a/modules/bindings/src/tmscore.f b/modules/bindings/src/tmscore.f new file mode 100644 index 0000000000000000000000000000000000000000..02886d7ab9ed606bd5e586682660347a3bc16900 --- /dev/null +++ b/modules/bindings/src/tmscore.f @@ -0,0 +1,887 @@ +************************************************************************* +* This program is to compare two protein structures and identify the +* best superposition that has the maximum TM-score. The program can +* be freely copied or modified. +* For comments, please email to: yzhang@ku.edu +* +* Reference: +* Yang Zhang, Jeffrey Skolnick, Proteins, 2004 57:702-10. +* +******************* Updating history ************************************ +* 2005/10/19: the program was reformed so that the score values +* are not dependent on the specific compilers. +* 2006/06/20: select 'A' if there is altLoc when reading PDB file +* 2007/02/05: fix a bug with length<15 in TMscore_32 +* 2007/02/27: rotation matrix from Chain-1 to Chain-2 is added +* 2007/12/06: GDT-HA score is added, fixed a bug for reading PDB +************************************************************************* + + program TMscore + PARAMETER(nmax=3000) + + common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0,d0_fix + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + dimension k_ali(nmax),k_ali0(nmax) + + character*100 fnam,pdb(100),outname + character*3 aa(-1:20),seqA(nmax),seqB(nmax) + character*100 s,du + character seq1A(nmax),seq1B(nmax),ali(nmax) + character sequenceA(nmax),sequenceB(nmax),sequenceM(nmax) + + dimension L_ini(100),iq(nmax) + common/scores/score,score_maxsub,score_fix,score10 + common/GDT/n_GDT05,n_GDT1,n_GDT2,n_GDT4,n_GDT8 + double precision score,score_max,score_fix,score_fix_max + double precision score_maxsub,score10 + dimension xa(nmax),ya(nmax),za(nmax) + +ccc RMSD: + double precision r_1(3,nmax),r_2(3,nmax),r_3(3,nmax),w(nmax) + double precision u(3,3),t(3),rms,drms !armsd is real + data w /nmax*1.0/ +ccc + + data aa/ 'BCK','GLY','ALA','SER','CYS', + & 'VAL','THR','ILE','PRO','MET', + & 'ASP','ASN','LEU','LYS','GLU', + & 'GLN','ARG','HIS','PHE','TYR', + & 'TRP','CYX'/ + character*1 slc(-1:20) + data slc/'X','G','A','S','C', + & 'V','T','I','P','M', + & 'D','N','L','K','E', + & 'Q','R','H','F','Y', + & 'W','C'/ + +*****instructions -----------------> + call getarg(1,fnam) + if(fnam.eq.' '.or.fnam.eq.'?'.or.fnam.eq.'-h')then + write(*,*) + write(*,*)'Brief instruction for running TM-score program:' + write(*,*) + write(*,*)'1. Run TM-score to compare ''model'' and ''native'':' + write(*,*)' TMscore model native' + write(*,*) + write(*,*)'2. Run TM-score with an assigned d0, e.g. 5 Angstroms:' + write(*,*)' TMscore model native -d 5' + write(*,*) + write(*,*)'3. Run TM-score with superposition output, e.g. ', + & '''TM.sup'':' + write(*,*)' TMscore model native -o TM.sup' + write(*,*) + write(*,*)'4, To view the superimposed structures by rasmol:' + write(*,*)' rasmol -script TM.sup' + write(*,*) + goto 9999 + endif + +******* options -----------> + m_out=-1 + m_fix=-1 + narg=iargc() + i=0 + j=0 + 115 continue + i=i+1 + call getarg(i,fnam) + if(fnam.eq.'-o')then + m_out=1 + i=i+1 + call getarg(i,outname) + elseif(fnam.eq.'-d')then + m_fix=1 + i=i+1 + call getarg(i,fnam) + read(fnam,*)d0_fix + else + j=j+1 + pdb(j)=fnam + endif + if(i.lt.narg)goto 115 + +ccccccccc read data from first CA file: + open(unit=10,file=pdb(1),status='old') + i=0 + 101 read(10,104,end=102) s + if(s(1:3).eq.'TER') goto 102 + if(s(1:4).eq.'ATOM')then + if(s(13:16).eq.'CA '.or.s(13:16).eq.' CA '.or.s(13:16). + & eq.' CA')then + if(s(17:17).eq.' '.or.s(17:17).eq.'A')then + i=i+1 + read(s,103)du,seqA(i),du,nresA(i),du,xa(i),ya(i),za(i) + do j=-1,20 + if(seqA(i).eq.aa(j))then + seq1A(i)=slc(j) + goto 21 + endif + enddo + seq1A(i)=slc(-1) + 21 continue + endif + endif + endif + goto 101 + 102 continue + 103 format(A17,A3,A2,i4,A4,3F8.3) + 104 format(A100) + close(10) + nseqA=i +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +ccccccccc read data from first CA file: + open(unit=10,file=pdb(2),status='old') + i=0 + 201 read(10,204,end=202) s + if(s(1:3).eq.'TER') goto 202 + if(s(1:4).eq.'ATOM')then + if(s(13:16).eq.'CA '.or.s(13:16).eq.' CA '.or.s(13:16). + & eq.' CA')then + if(s(17:17).eq.' '.or.s(17:17).eq.'A')then + i=i+1 + read(s,203)du,seqB(i),du,nresB(i),du,xb(i),yb(i),zb(i) + do j=-1,20 + if(seqB(i).eq.aa(j))then + seq1B(i)=slc(j) + goto 22 + endif + enddo + seq1B(i)=slc(-1) + 22 continue + endif + endif + endif + goto 201 + 202 continue + 203 format(A17,A3,A2,i4,A4,3F8.3) + 204 format(A100) + close(10) + nseqB=i +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +****************************************************************** +* pickup the aligned residues: +****************************************************************** + k=0 + do i=1,nseqA + do j=1,nseqB + if(nresA(i).eq.nresB(j))then + k=k+1 + iA(k)=i + iB(k)=j + goto 205 + endif + enddo + 205 continue + enddo + n_ali=k !number of aligned residues + if(n_ali.lt.1)then + write(*,*)'There is no common residues in the input structures' + goto 9999 + endif + +************///// +* parameters: +***************** +*** d0-------------> + if(nseqB.gt.15)then + d0=1.24*(nseqB-15)**(1.0/3.0)-1.8 + else + d0=0.5 + endif + if(d0.lt.0.5)d0=0.5 + if(m_fix.eq.1)d0=d0_fix +*** d0_search -----> + d0_search=d0 + if(d0_search.gt.8)d0_search=8 + if(d0_search.lt.4.5)d0_search=4.5 +*** iterative parameters -----> + n_it=20 !maximum number of iterations + d_output=5 !for output alignment + if(m_fix.eq.1)d_output=d0_fix + n_init_max=6 !maximum number of L_init + n_init=0 + L_ini_min=4 + if(n_ali.lt.4)L_ini_min=n_ali + do i=1,n_init_max-1 + n_init=n_init+1 + L_ini(n_init)=n_ali/2**(n_init-1) + if(L_ini(n_init).le.L_ini_min)then + L_ini(n_init)=L_ini_min + goto 402 + endif + enddo + n_init=n_init+1 + L_ini(n_init)=L_ini_min + 402 continue + +****************************************************************** +* find the maximum score starting from local structures superposition +****************************************************************** + score_max=-1 !TM-score + score_maxsub_max=-1 !MaxSub-score + score10_max=-1 !TM-score10 + n_GDT05_max=-1 !number of residues<0.5 + n_GDT1_max=-1 !number of residues<1 + n_GDT2_max=-1 !number of residues<2 + n_GDT4_max=-1 !number of residues<4 + n_GDT8_max=-1 !number of residues<8 + do 333 i_init=1,n_init + L_init=L_ini(i_init) + iL_max=n_ali-L_init+1 + do 300 iL=1,iL_max !on aligned residues, [1,nseqA] + LL=0 + ka=0 + do i=1,L_init + k=iL+i-1 ![1,n_ali] common aligned + r_1(1,i)=xa(iA(k)) + r_1(2,i)=ya(iA(k)) + r_1(3,i)=za(iA(k)) + r_2(1,i)=xb(iB(k)) + r_2(2,i)=yb(iB(k)) + r_2(3,i)=zb(iB(k)) + ka=ka+1 + k_ali(ka)=k + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + if(i_init.eq.1)then !global superposition + armsd=dsqrt(rms/LL) + rmsd_ali=armsd + endif + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + d=d0_search-1 + call score_fun !init, get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka0 + k_ali0(i)=k_ali(i) + enddo + endif + if(score10_max.lt.score10)score10_max=score10 + if(score_maxsub_max.lt.score_maxsub)score_maxsub_max= + & score_maxsub + if(n_GDT05_max.lt.n_GDT05)n_GDT05_max=n_GDT05 + if(n_GDT1_max.lt.n_GDT1)n_GDT1_max=n_GDT1 + if(n_GDT2_max.lt.n_GDT2)n_GDT2_max=n_GDT2 + if(n_GDT4_max.lt.n_GDT4)n_GDT4_max=n_GDT4 + if(n_GDT8_max.lt.n_GDT8)n_GDT8_max=n_GDT8 +*** iteration for extending ----------------------------------> + d=d0_search+1 + do 301 it=1,n_it + LL=0 + ka=0 + do i=1,n_cut + m=i_ali(i) ![1,n_ali] + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + ka=ka+1 + k_ali(ka)=m + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + call score_fun !get scores, n_cut+i_ali(i) for iteration + if(score_max.lt.score)then + score_max=score + ka0=ka + do i=1,ka + k_ali0(i)=k_ali(i) + enddo + endif + if(score10_max.lt.score10)score10_max=score10 + if(score_maxsub_max.lt.score_maxsub)score_maxsub_max + & =score_maxsub + if(n_GDT05_max.lt.n_GDT05)n_GDT05_max=n_GDT05 + if(n_GDT1_max.lt.n_GDT1)n_GDT1_max=n_GDT1 + if(n_GDT2_max.lt.n_GDT2)n_GDT2_max=n_GDT2 + if(n_GDT4_max.lt.n_GDT4)n_GDT4_max=n_GDT4 + if(n_GDT8_max.lt.n_GDT8)n_GDT8_max=n_GDT8 + 303 format(i5,i5,i5,f17.14,f17.14,i5,f7.3) + if(it.eq.n_it)goto 302 + if(n_cut.eq.ka)then + neq=0 + do i=1,n_cut + if(i_ali(i).eq.k_ali(i))neq=neq+1 + enddo + if(n_cut.eq.neq)goto 302 + endif + 301 continue !for iteration + 302 continue + 300 continue !for shift + 333 continue !for initial length, L_ali/M + +****************************************************************** +* Output +****************************************************************** +*** output TM-scale ----------------------------> + write(*,*) + write(*,*)'*****************************************************', + & '************************' + write(*,*)'* TM-SCORE ', + & ' *' + write(*,*)'* A scoring function to assess the quality of protein', + & ' structure predictions *' + write(*,*)'* Based on statistics: ', + & ' *' + write(*,*)'* 0.0 < TM-score < 0.17, Random predictions ', + & ' *' + write(*,*)'* 0.4 < TM-score < 1.00, Meaningful predictions', + & ' *' + write(*,*)'* Reference: Yang Zhang and Jeffrey Skolnick, ', + & 'Proteins 2004 57: 702-710 *' + write(*,*)'* For comments, please email to: yzhang@ku.edu ', + & ' *' + write(*,*)'*****************************************************', + & '************************' + write(*,*) + write(*,501)pdb(1),nseqA + 501 format('Structure1: ',A10,' Length= ',I4) + write(*,502)pdb(2),nseqB + 502 format('Structure2: ',A10,' Length= ',I4, + & ' (by which all scores are normalized)') + write(*,503)n_ali + 503 format('Number of residues in common= ',I4) + write(*,513)rmsd_ali + 513 format('RMSD of the common residues= ',F8.3) + write(*,*) + write(*,504)score_max,d0,score10_max + 504 format('TM-score = ',f6.4,' (d0=',f5.2,',',' TM10= ',f6.4,')') + write(*,505)score_maxsub_max + 505 format('MaxSub-score= ',f6.4,' (d0= 3.50)') + score_GDT=(n_GDT1_max+n_GDT2_max+n_GDT4_max+n_GDT8_max) + & /float(4*nseqB) + write(*,506)score_GDT,n_GDT1_max/float(nseqB),n_GDT2_max + & /float(nseqB),n_GDT4_max/float(nseqB),n_GDT8_max/float(nseqB) + 506 format('GDT-TS-score= ',f6.4,' %(d<1)=',f6.4,' %(d<2)=',f6.4, + $ ' %(d<4)=',f6.4,' %(d<8)=',f6.4) + score_GDT_HA=(n_GDT05_max+n_GDT1_max+n_GDT2_max+n_GDT4_max) + & /float(4*nseqB) + write(*,507)score_GDT_HA,n_GDT05_max/float(nseqB),n_GDT1_max + & /float(nseqB),n_GDT2_max/float(nseqB),n_GDT4_max/float(nseqB) + 507 format('GDT-HA-score= ',f6.4,' %(d<0.5)=',f6.4,' %(d<1)=',f6.4, + $ ' %(d<2)=',f6.4,' %(d<4)=',f6.4) + write(*,*) + +*** recall and output the superposition of maxiumum TM-score: + LL=0 + do i=1,ka0 + m=k_ali0(i) !record of the best alignment + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,1,rms,u,t,ier) !u rotate r_1 to r_2 + do j=1,nseqA + xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) + yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) + zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) + enddo + +********* extract rotation matrix ------------> + write(*,*)'-------- rotation matrix to rotate Chain-1 to ', + & 'Chain-2 ------' + write(*,*)'i t(i) u(i,1) u(i,2) ', + & ' u(i,3)' + do i=1,3 + write(*,304)i,t(i),u(i,1),u(i,2),u(i,3) + enddo +c do j=1,nseqA +c xt(j)=t(1)+u(1,1)*xa(j)+u(1,2)*ya(j)+u(1,3)*za(j) +c yt(j)=t(2)+u(2,1)*xa(j)+u(2,2)*ya(j)+u(2,3)*za(j) +c zt(j)=t(3)+u(3,1)*xa(j)+u(3,2)*ya(j)+u(3,3)*za(j) +c write(*,*)j,xt(j),yt(j),zt(j) +c enddo + write(*,*) + 304 format(I2,f18.10,f15.10,f15.10,f15.10) + +********* rmsd in superposed regions ---------------> + d=d_output !for output + call score_fun() !give i_ali(i), score_max=score now + LL=0 + do i=1,n_cut + m=i_ali(i) ![1,nseqA] + r_1(1,i)=xa(iA(m)) + r_1(2,i)=ya(iA(m)) + r_1(3,i)=za(iA(m)) + r_2(1,i)=xb(iB(m)) + r_2(2,i)=yb(iB(m)) + r_2(3,i)=zb(iB(m)) + LL=LL+1 + enddo + call u3b(w,r_1,r_2,LL,0,rms,u,t,ier) + armsd=dsqrt(rms/LL) + rmsd=armsd + +*** output rotated chain1 + chain2-----> + if(m_out.ne.1)goto 999 + OPEN(unit=7,file=outname,status='unknown') !pdb1.aln + pdb2.aln + 900 format(A) + 901 format('select ',I4) + write(7,900)'load inline' + write(7,900)'select atomno<1000' +c write(7,900)'color [255,20,147]' + write(7,900)'wireframe .45' + write(7,900)'select none' + write(7,900)'select atomno>1000' +c write(7,900)'color [100,149,237]' + write(7,900)'wireframe .15' + write(7,900)'color white' + do i=1,n_cut + write(7,901)nresA(iA(i_ali(i))) + write(7,900)'color red' + enddo + write(7,900)'select all' + write(7,900)'exit' + write(7,514)rmsd_ali + 514 format('REMARK RMSD of the common residues=',F8.3) + write(7,515)score_max,d0 + 515 format('REMARK TM-score=',f6.4,' (d0=',f5.2,')') + do i=1,nseqA + write(7,1237)nresA(i),seqA(i),nresA(i),xt(i),yt(i),zt(i) + enddo + write(7,1238) + do i=2,nseqA + write(7,1239)nresA(i-1),nresA(i) + enddo + do i=1,nseqB + write(7,1237)2000+nresB(i),seqB(i),nresB(i),xb(i),yb(i),zb(i) + enddo + write(7,1238) + do i=2,nseqB + write(7,1239)2000+nresB(i-1),2000+nresB(i) + enddo + 1237 format('ATOM ',i5,' CA ',A3,I6,4X,3F8.3) + 1238 format('TER') + 1239 format('CONECT',I5,I5) + 999 continue + +*** record aligned residues by i=[1,nseqA], for sequenceM()------------> + do i=1,nseqA + iq(i)=0 + enddo + do i=1,n_cut + j=iA(i_ali(i)) ![1,nseqA] + k=iB(i_ali(i)) ![1,nseqB] + dis=sqrt((xt(j)-xb(k))**2+(yt(j)-yb(k))**2+(zt(j)-zb(k))**2) + if(dis.lt.d_output)then + iq(j)=1 + endif + enddo +******************************************************************* +*** output aligned sequences + k=0 + i=1 + j=1 + 800 continue + if(i.gt.nseqA.and.j.gt.nseqB)goto 802 + if(i.gt.nseqA.and.j.le.nseqB)then + k=k+1 + sequenceA(k)='-' + sequenceB(k)=seq1B(j) + sequenceM(k)=' ' + j=j+1 + goto 800 + endif + if(i.le.nseqA.and.j.gt.nseqB)then + k=k+1 + sequenceA(k)=seq1A(i) + sequenceB(k)='-' + sequenceM(k)=' ' + i=i+1 + goto 800 + endif + if(nresA(i).eq.nresB(j))then + k=k+1 + sequenceA(k)=seq1A(i) + sequenceB(k)=seq1B(j) + if(iq(i).eq.1)then + sequenceM(k)=':' + else + sequenceM(k)=' ' + endif + i=i+1 + j=j+1 + goto 800 + elseif(nresA(i).lt.nresB(j))then + k=k+1 + sequenceA(k)=seq1A(i) + sequenceB(k)='-' + sequenceM(k)=' ' + i=i+1 + goto 800 + elseif(nresB(j).lt.nresA(i))then + k=k+1 + sequenceA(k)='-' + sequenceB(k)=seq1B(j) + sequenceM(k)=' ' + j=j+1 + goto 800 + endif + 802 continue + + write(*,600)d_output,n_cut,rmsd + 600 format('Superposition in the TM-score: Length(d<',f3.1, + $ ')=',i3,' RMSD=',f6.2) + write(*,603)d_output + 603 format('(":" denotes the residue pairs of distance < ',f3.1, + & ' Angstrom)') + write(*,601)(sequenceA(i),i=1,k) + write(*,601)(sequenceM(i),i=1,k) + write(*,601)(sequenceB(i),i=1,k) + write(*,602)(mod(i,10),i=1,k) + 601 format(2000A1) + 602 format(2000I1) + write(*,*) + +c^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 9999 END + +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +c 1, collect those residues with dis<d; +c 2, calculate score_GDT, score_maxsub, score_TM +ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + subroutine score_fun + PARAMETER(nmax=3000) + + common/stru/xt(nmax),yt(nmax),zt(nmax),xb(nmax),yb(nmax),zb(nmax) + common/nres/nresA(nmax),nresB(nmax),nseqA,nseqB + common/para/d,d0,d0_fix + common/align/n_ali,iA(nmax),iB(nmax) + common/nscore/i_ali(nmax),n_cut ![1,n_ali],align residues for the score + common/scores/score,score_maxsub,score_fix,score10 + common/GDT/n_GDT05,n_GDT1,n_GDT2,n_GDT4,n_GDT8 + double precision score,score_max,score_fix,score_fix_max + double precision score_maxsub,score10 + + d_tmp=d + 21 n_cut=0 !number of residue-pairs dis<d, for iteration + n_GDT05=0 !for GDT-score, # of dis<0.5 + n_GDT1=0 !for GDT-score, # of dis<1 + n_GDT2=0 !for GDT-score, # of dis<2 + n_GDT4=0 !for GDT-score, # of dis<4 + n_GDT8=0 !for GDT-score, # of dis<8 + score_maxsub_sum=0 !Maxsub-score + score_sum=0 !TMscore + score_sum10=0 !TMscore10 + do k=1,n_ali + i=iA(k) ![1,nseqA] reoder number of structureA + j=iB(k) ![1,nseqB] + dis=sqrt((xt(i)-xb(j))**2+(yt(i)-yb(j))**2+(zt(i)-zb(j))**2) +*** for iteration: + if(dis.lt.d_tmp)then + n_cut=n_cut+1 + i_ali(n_cut)=k ![1,n_ali], mark the residue-pairs in dis<d + endif +*** for GDT-score: + if(dis.le.8)then + n_GDT8=n_GDT8+1 + if(dis.le.4)then + n_GDT4=n_GDT4+1 + if(dis.le.2)then + n_GDT2=n_GDT2+1 + if(dis.le.1)then + n_GDT1=n_GDT1+1 + if(dis.le.0.5)then + n_GDT05=n_GDT05+1 + endif + endif + endif + endif + endif +*** for MAXsub-score: + if(dis.lt.3.5)then + score_maxsub_sum=score_maxsub_sum+1/(1+(dis/3.5)**2) + endif +*** for TM-score: + score_sum=score_sum+1/(1+(dis/d0)**2) +*** for TM-score10: + if(dis.lt.10)then + score_sum10=score_sum10+1/(1+(dis/d0)**2) + endif + enddo + if(n_cut.lt.3.and.n_ali.gt.3)then + d_tmp=d_tmp+.5 + goto 21 + endif + score_maxsub=score_maxsub_sum/float(nseqB) !MAXsub-score + score=score_sum/float(nseqB) !TM-score + score10=score_sum10/float(nseqB) !TM-score10 + + return + end + +cccccccccccccccc Calculate sum of (r_d-r_m)^2 cccccccccccccccccccccccccc +c w - w(m) is weight for atom pair c m (given) +c x - x(i,m) are coordinates of atom c m in set x (given) +c y - y(i,m) are coordinates of atom c m in set y (given) +c n - n is number of atom pairs (given) +c mode - 0:calculate rms only (given) +c 1:calculate rms,u,t (takes longer) +c rms - sum of w*(ux+t-y)**2 over all atom pairs (result) +c u - u(i,j) is rotation matrix for best superposition (result) +c t - t(i) is translation vector for best superposition (result) +c ier - 0: a unique optimal superposition has been determined(result) +c -1: superposition is not unique but optimal +c -2: no result obtained because of negative weights w +c or all weights equal to zero. +cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc + subroutine u3b(w, x, y, n, mode, rms, u, t, ier) + integer ip(9), ip2312(4), i, j, k, l, m1, m, ier, n, mode + double precision w(1), x(3, 1), y(3, 1), u(3, 3), t(3), rms, sigma + double precision r(3, 3), xc(3), yc(3), wc, a(3, 3), b(3, 3), e0, + &e(3), e1, e2, e3, d, spur, det, cof, h, g, cth, sth, sqrth, p, tol + &, rr(6), rr1, rr2, rr3, rr4, rr5, rr6, ss(6), ss1, ss2, ss3, ss4, + &ss5, ss6, zero, one, two, three, sqrt3 + equivalence (rr(1), rr1), (rr(2), rr2), (rr(3), rr3), (rr(4), rr4) + &, (rr(5), rr5), (rr(6), rr6), (ss(1), ss1), (ss(2), ss2), (ss(3), + &ss3), (ss(4), ss4), (ss(5), ss5), (ss(6), ss6), (e(1), e1), (e(2) + &, e2), (e(3), e3) + data sqrt3 / 1.73205080756888d+00 / + data tol / 1.0d-2 / + data zero / 0.0d+00 / + data one / 1.0d+00 / + data two / 2.0d+00 / + data three / 3.0d+00 / + data ip / 1, 2, 4, 2, 3, 5, 4, 5, 6 / + data ip2312 / 2, 3, 1, 2 / +c 156 "rms.for" + wc = zero + rms = 0.0 + e0 = zero + do 1 i = 1, 3 + xc(i) = zero + yc(i) = zero + t(i) = 0.0 + do 1 j = 1, 3 + d = zero + if (i .eq. j) d = one + u(i,j) = d + a(i,j) = d + 1 r(i,j) = zero + ier = -1 +c**** DETERMINE CENTROIDS OF BOTH VECTOR SETS X AND Y +c 170 "rms.for" + if (n .lt. 1) return +c 172 "rms.for" + ier = -2 + do 2 m = 1, n + if (w(m) .lt. 0.0) return + wc = wc + w(m) + do 2 i = 1, 3 + xc(i) = xc(i) + (w(m) * x(i,m)) + 2 yc(i) = yc(i) + (w(m) * y(i,m)) + if (wc .le. zero) return + do 3 i = 1, 3 + xc(i) = xc(i) / wc +c**** DETERMINE CORRELATION MATRIX R BETWEEN VECTOR SETS Y AND X +c 182 "rms.for" + 3 yc(i) = yc(i) / wc +c 184 "rms.for" + do 4 m = 1, n + do 4 i = 1, 3 + e0 = e0 + (w(m) * (((x(i,m) - xc(i)) ** 2) + ((y(i,m) - yc(i)) ** + &2))) +c 187 "rms.for" + d = w(m) * (y(i,m) - yc(i)) + do 4 j = 1, 3 +c**** CALCULATE DETERMINANT OF R(I,J) +c 189 "rms.for" + 4 r(i,j) = r(i,j) + (d * (x(j,m) - xc(j))) +c 191 "rms.for" + det = ((r(1,1) * ((r(2,2) * r(3,3)) - (r(2,3) * r(3,2)))) - (r(1,2 + &) * ((r(2,1) * r(3,3)) - (r(2,3) * r(3,1))))) + (r(1,3) * ((r(2,1) + & * r(3,2)) - (r(2,2) * r(3,1)))) +c**** FORM UPPER TRIANGLE OF TRANSPOSED(R)*R +c 194 "rms.for" + sigma = det +c 196 "rms.for" + m = 0 + do 5 j = 1, 3 + do 5 i = 1, j + m = m + 1 +c***************** EIGENVALUES ***************************************** +c**** FORM CHARACTERISTIC CUBIC X**3-3*SPUR*X**2+3*COF*X-DET=0 +c 200 "rms.for" + 5 rr(m) = ((r(1,i) * r(1,j)) + (r(2,i) * r(2,j))) + (r(3,i) * r(3,j) + &) +c 203 "rms.for" + spur = ((rr1 + rr3) + rr6) / three + cof = ((((((rr3 * rr6) - (rr5 * rr5)) + (rr1 * rr6)) - (rr4 * rr4) + &) + (rr1 * rr3)) - (rr2 * rr2)) / three +c 205 "rms.for" + det = det * det + do 6 i = 1, 3 + 6 e(i) = spur +c**** REDUCE CUBIC TO STANDARD FORM Y**3-3HY+2G=0 BY PUTTING X=Y+SPUR +c 208 "rms.for" + if (spur .le. zero) goto 40 +c 210 "rms.for" + d = spur * spur + h = d - cof +c**** SOLVE CUBIC. ROOTS ARE E1,E2,E3 IN DECREASING ORDER +c 212 "rms.for" + g = (((spur * cof) - det) / two) - (spur * h) +c 214 "rms.for" + if (h .le. zero) goto 8 + sqrth = dsqrt(h) + d = ((h * h) * h) - (g * g) + if (d .lt. zero) d = zero + d = datan2(dsqrt(d),- g) / three + cth = sqrth * dcos(d) + sth = (sqrth * sqrt3) * dsin(d) + e1 = (spur + cth) + cth + e2 = (spur - cth) + sth + e3 = (spur - cth) - sth +c.....HANDLE SPECIAL CASE OF 3 IDENTICAL ROOTS +c 224 "rms.for" + if (mode) 10, 50, 10 +c**************** EIGENVECTORS ***************************************** +c 226 "rms.for" + 8 if (mode) 30, 50, 30 +c 228 "rms.for" + 10 do 15 l = 1, 3, 2 + d = e(l) + ss1 = ((d - rr3) * (d - rr6)) - (rr5 * rr5) + ss2 = ((d - rr6) * rr2) + (rr4 * rr5) + ss3 = ((d - rr1) * (d - rr6)) - (rr4 * rr4) + ss4 = ((d - rr3) * rr4) + (rr2 * rr5) + ss5 = ((d - rr1) * rr5) + (rr2 * rr4) + ss6 = ((d - rr1) * (d - rr3)) - (rr2 * rr2) + j = 1 + if (dabs(ss1) .ge. dabs(ss3)) goto 12 + j = 2 + if (dabs(ss3) .ge. dabs(ss6)) goto 13 + 11 j = 3 + goto 13 + 12 if (dabs(ss1) .lt. dabs(ss6)) goto 11 + 13 d = zero + j = 3 * (j - 1) + do 14 i = 1, 3 + k = ip(i + j) + a(i,l) = ss(k) + 14 d = d + (ss(k) * ss(k)) + if (d .gt. zero) d = one / dsqrt(d) + do 15 i = 1, 3 + 15 a(i,l) = a(i,l) * d + d = ((a(1,1) * a(1,3)) + (a(2,1) * a(2,3))) + (a(3,1) * a(3,3)) + m1 = 3 + m = 1 + if ((e1 - e2) .gt. (e2 - e3)) goto 16 + m1 = 1 + m = 3 + 16 p = zero + do 17 i = 1, 3 + a(i,m1) = a(i,m1) - (d * a(i,m)) + 17 p = p + (a(i,m1) ** 2) + if (p .le. tol) goto 19 + p = one / dsqrt(p) + do 18 i = 1, 3 + 18 a(i,m1) = a(i,m1) * p + goto 21 + 19 p = one + do 20 i = 1, 3 + if (p .lt. dabs(a(i,m))) goto 20 + p = dabs(a(i,m)) + j = i + 20 continue + k = ip2312(j) + l = ip2312(j + 1) + p = dsqrt((a(k,m) ** 2) + (a(l,m) ** 2)) + if (p .le. tol) goto 40 + a(j,m1) = zero + a(k,m1) = - (a(l,m) / p) + a(l,m1) = a(k,m) / p + 21 a(1,2) = (a(2,3) * a(3,1)) - (a(2,1) * a(3,3)) + a(2,2) = (a(3,3) * a(1,1)) - (a(3,1) * a(1,3)) +c****************** ROTATION MATRIX ************************************ +c 282 "rms.for" + a(3,2) = (a(1,3) * a(2,1)) - (a(1,1) * a(2,3)) +c 284 "rms.for" + 30 do 32 l = 1, 2 + d = zero + do 31 i = 1, 3 + b(i,l) = ((r(i,1) * a(1,l)) + (r(i,2) * a(2,l))) + (r(i,3) * a(3,l + &)) +c 288 "rms.for" + 31 d = d + (b(i,l) ** 2) + if (d .gt. zero) d = one / dsqrt(d) + do 32 i = 1, 3 + 32 b(i,l) = b(i,l) * d + d = ((b(1,1) * b(1,2)) + (b(2,1) * b(2,2))) + (b(3,1) * b(3,2)) + p = zero + do 33 i = 1, 3 + b(i,2) = b(i,2) - (d * b(i,1)) + 33 p = p + (b(i,2) ** 2) + if (p .le. tol) goto 35 + p = one / dsqrt(p) + do 34 i = 1, 3 + 34 b(i,2) = b(i,2) * p + goto 37 + 35 p = one + do 36 i = 1, 3 + if (p .lt. dabs(b(i,1))) goto 36 + p = dabs(b(i,1)) + j = i + 36 continue + k = ip2312(j) + l = ip2312(j + 1) + p = dsqrt((b(k,1) ** 2) + (b(l,1) ** 2)) + if (p .le. tol) goto 40 + b(j,2) = zero + b(k,2) = - (b(l,1) / p) + b(l,2) = b(k,1) / p + 37 b(1,3) = (b(2,1) * b(3,2)) - (b(2,2) * b(3,1)) + b(2,3) = (b(3,1) * b(1,2)) - (b(3,2) * b(1,1)) + b(3,3) = (b(1,1) * b(2,2)) - (b(1,2) * b(2,1)) + do 39 i = 1, 3 + do 39 j = 1, 3 +c****************** TRANSLATION VECTOR ********************************* +c 320 "rms.for" + 39 u(i,j) = ((b(i,1) * a(j,1)) + (b(i,2) * a(j,2))) + (b(i,3) * a(j,3 + &)) + 40 do 41 i = 1, 3 +c********************** RMS ERROR ************************************** +c 323 "rms.for" + 41 t(i) = ((yc(i) - (u(i,1) * xc(1))) - (u(i,2) * xc(2))) - (u(i,3) + & * xc(3)) + 50 do 51 i = 1, 3 + if (e(i) .lt. zero) e(i) = zero + 51 e(i) = dsqrt(e(i)) + ier = 0 + if (e2 .le. (e1 * 1.0d-05)) ier = -1 + d = e3 + if (sigma .ge. 0.0) goto 52 + d = - d + if ((e2 - e3) .le. (e1 * 1.0d-05)) ier = -1 + 52 d = (d + e2) + e1 + rms = (e0 - d) - d + if (rms .lt. 0.0) rms = 0.0 + return +c.....END U3B........................................................... +c---------------------------------------------------------- +c THE END +c---------------------------------------------------------- +c 338 "rms.for" + end \ No newline at end of file