00001 """
00002 Functions to calculate helix kinks: bend, face shift and wobbla angles
00003
00004 Author: Niklaus Johner
00005 """
00006
00007 import os
00008 import ost
00009
00010 def __FindProline(sele,proline):
00011 if not sele.IsValid():
00012 print 'selection is not valid'
00013 raise RuntimeError
00014 if proline==False:
00015 proline=sele.Select('rname=PRO')
00016 if not proline.GetResidueCount()==1:
00017 print proline.GetResidueCount(),'prolines in the selection. One proline is needed'
00018 raise RuntimeError
00019 proline=proline.residues[0]
00020 proline_ca=proline.FindAtom('CA')
00021 if not proline_ca.IsValid():
00022 print 'proline has no CA atom'
00023 raise RuntimeError
00024 return (proline,proline_ca)
00025 proline.GetNumber().num
00026
00027 def __SelectPreAndPostProline(sele,proline_num):
00028 pre_proline=sele.Select('rnum<'+str(proline_num))
00029 post_proline=sele.Select('rnum>'+str(proline_num))
00030 print 'pre-proline residues'
00031 for res in pre_proline.residues:
00032 print res
00033 print 'post-proline residues'
00034 for res in post_proline.residues:
00035 print res
00036 if pre_proline.GetResidueCount()<4 or post_proline.GetResidueCount()<4:
00037 print 'pre and post proline helices should be at least 4 residues long, 7 for better stability'
00038 raise RuntimeError
00039 return (pre_proline,post_proline)
00040
00041 def __FindCa3AndCa4(sele,proline_ca,proline_num):
00042 ca_3=sele.FindAtom(proline_ca.GetHandle().GetChain().GetName(),proline_num-3,'CA')
00043 ca_4=sele.FindAtom(proline_ca.GetHandle().GetChain().GetName(),proline_num-4,'CA')
00044 if not (ca_3.IsValid() and ca_4.IsValid()):
00045 print 'CA not found in (i-4) or (i-3) residue'
00046 raise RuntimeError
00047 return (ca_3,ca_4)
00048
00049
00050 def __CalculateBendAngle(pre_proline_axis,post_proline_axis):
00051 return ost.geom.Angle(pre_proline_axis,post_proline_axis)
00052
00053 def __CalculateWobbleAngle(pre_proline_axis,post_proline_axis,post_proline_centers,proline_pos):
00054 p1=proline_pos-post_proline_centers
00055 n1=p1-ost.geom.Dot(p1,post_proline_axis)*post_proline_axis
00056 p2=-pre_proline_axis
00057 n2=p2-ost.geom.Dot(p2,post_proline_axis)*post_proline_axis
00058 sign=ost.geom.Dot(ost.geom.Cross(pre_proline_axis,n2),n2-n1)
00059 sign=sign/abs(sign)
00060 return sign*ost.geom.Angle(n1,n2)
00061
00062 def __CalculateFaceShift(pre_proline_axis,post_proline_axis,pre_proline_centers,post_proline_centers,proline_pos,ca3_pos,ca4_pos,bend_angle):
00063 p1=proline_pos-post_proline_centers
00064 n1=p1-ost.geom.Dot(p1,post_proline_axis)*post_proline_axis
00065 p2=(ca3_pos+ca4_pos)/2.0-pre_proline_centers
00066 n2=p2-ost.geom.Dot(p2,pre_proline_axis)*pre_proline_axis
00067
00068 R=ost.geom.AxisRotation(ost.geom.Cross(post_proline_axis,pre_proline_axis),bend_angle)
00069 n1=R*n1
00070
00071 sign=ost.geom.Dot(ost.geom.Cross(pre_proline_axis,n2),n2-n1)
00072 sign=sign/abs(sign)
00073 return sign*ost.geom.Angle(n1,n2)
00074
00075
00076 def AnalyzeHelixKink(t,sele,proline=False):
00077 """
00078 This function calculates the bend,wobble and face-shift angles
00079 in an alpha-helix over a trajectory. The determination is more stable if
00080 there are at least 4 residues on each side (8 is even better) of the proline around which
00081 the helix is kinked. The selection should contain all residues in the correct
00082 order and with no gaps and no missing C-alphas.
00083
00084 :param t: The trajectory to be analyzed
00085 :type t: `~ost.mol.CoordGroup`
00086 :param sele: A selection containing the alpha helix to be analyzed
00087 :type sele: :class:`~ost.mol.EntityView`
00088 :param proline=False: A selection containing only the proline (or another residue) around
00089 which the helix is kinked. If False, the proline will be serached for automatically
00090 :type proline: :class:`ost.mol.EntityView`
00091
00092 :return: A tuple (bend_angle, face_shift, wobble_angle).
00093 :rtype: (FloatList, FLoatList, FloatList)
00094 """
00095 n_frames=t.GetFrameCount()
00096 (proline,proline_ca)=__FindProline(sele,proline)
00097 proline_num=proline.GetNumber().num
00098 (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num)
00099 (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num)
00100
00101 pre_proline_axis=ost.geom.Vec3List()
00102 post_proline_axis=ost.geom.Vec3List()
00103 pre_proline_centers=ost.geom.Vec3List()
00104 post_proline_centers=ost.geom.Vec3List()
00105 ost.mol.alg.AnalyzeAlphaHelixAxis(t,pre_proline,pre_proline_axis,pre_proline_centers)
00106 ost.mol.alg.AnalyzeAlphaHelixAxis(t,post_proline,post_proline_axis,post_proline_centers)
00107 proline_pos=ost.mol.alg.AnalyzeAtomPos(t,proline_ca.GetHandle())
00108 ca3_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_3.GetHandle())
00109 ca4_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_4.GetHandle())
00110
00111 bend_angle=ost.FloatList()
00112 face_shift=ost.FloatList()
00113 wobble_angle=ost.FloatList()
00114 for i in range(n_frames):
00115 bend_angle.append(__CalculateBendAngle(pre_proline_axis[i],post_proline_axis[i]))
00116 face_shift.append(__CalculateFaceShift(pre_proline_axis[i],post_proline_axis[i],pre_proline_centers[i],post_proline_centers[i],proline_pos[i],ca3_pos[i],ca4_pos[i],bend_angle[i]))
00117 wobble_angle.append(__CalculateWobbleAngle(pre_proline_axis[i],post_proline_axis[i],post_proline_centers[i],proline_pos[i]))
00118 return (bend_angle,face_shift,wobble_angle)
00119
00120
00121 def CalculateHelixKink(sele,proline=False):
00122 """
00123 This function calculates the bend,wobble and face-shift angles
00124 in an alpha-helix of an EntityView. The determination is more stable if
00125 there are at least 4 residues on each side (8 is even better) of the prolin around which
00126 the helix is kinked. The selection should contain all residues in the correct
00127 order and with no gaps and no missing C-alphas.
00128
00129 :param sele: A selection containing the alpha helix to be analyzed
00130 :type sele: :class:`~ost.mol.EntityView`
00131 :param proline=False: A selection containing only the proline (or another residue) around
00132 which the helix is kinked. If False, the proline will be serached for automatically
00133 :type proline: :class:`ost.mol.EntityView`
00134
00135 :return: A tuple (bend_angle, face_shift, wobble_angle).
00136 :rtype: (float, float, float)
00137 """
00138 (proline,proline_ca)=__FindProline(sele,proline)
00139 proline_num=proline.GetNumber().num
00140 (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num)
00141 (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num)
00142
00143 pre_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(pre_proline)
00144 post_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(post_proline)
00145 prepa=pre_proline_axis.GetDirection()
00146 prepc=pre_proline_axis.GetOrigin()
00147 postpa=post_proline_axis.GetDirection()
00148 postpc=post_proline_axis.GetOrigin()
00149
00150 bend=__CalculateBendAngle(prepa,postpa)
00151 wobble=__CalculateWobbleAngle(prepa,postpa,postpc,proline_ca.pos)
00152 shift=__CalculateFaceShift(prepa,postpa,prepc,postpc,proline_ca.pos,ca_3.pos,ca_4.pos,bend)
00153 return (bend,shift,wobble)
00154
00155
00156
00157