00001 """
00002 Functions to calculate helix kinks: bend, face shift and wobble 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 in an alpha-
00079 helix over a trajectory. The determination is more stable if there are at
00080 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: :class:`~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: A selection containing only the proline (or another residue)
00089 around which the helix is kinked. If False, the proline will
00090 be searched for automatically
00091 :type proline: :class:`ost.mol.EntityView`
00092
00093 :return: A tuple (bend_angle, face_shift, wobble_angle).
00094 :rtype: (FloatList, FLoatList, FloatList)
00095 """
00096 n_frames=t.GetFrameCount()
00097 (proline,proline_ca)=__FindProline(sele,proline)
00098 proline_num=proline.GetNumber().num
00099 (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num)
00100 (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num)
00101
00102 pre_proline_axis=ost.geom.Vec3List()
00103 post_proline_axis=ost.geom.Vec3List()
00104 pre_proline_centers=ost.geom.Vec3List()
00105 post_proline_centers=ost.geom.Vec3List()
00106 ost.mol.alg.AnalyzeAlphaHelixAxis(t,pre_proline,pre_proline_axis,pre_proline_centers)
00107 ost.mol.alg.AnalyzeAlphaHelixAxis(t,post_proline,post_proline_axis,post_proline_centers)
00108 proline_pos=ost.mol.alg.AnalyzeAtomPos(t,proline_ca.GetHandle())
00109 ca3_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_3.GetHandle())
00110 ca4_pos=ost.mol.alg.AnalyzeAtomPos(t,ca_4.GetHandle())
00111
00112 bend_angle=ost.FloatList()
00113 face_shift=ost.FloatList()
00114 wobble_angle=ost.FloatList()
00115 for i in range(n_frames):
00116 bend_angle.append(__CalculateBendAngle(pre_proline_axis[i],post_proline_axis[i]))
00117 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]))
00118 wobble_angle.append(__CalculateWobbleAngle(pre_proline_axis[i],post_proline_axis[i],post_proline_centers[i],proline_pos[i]))
00119 return (bend_angle,face_shift,wobble_angle)
00120
00121
00122 def CalculateHelixKink(sele, proline=False):
00123 """
00124 This function calculates the bend, wobble and face-shift angles in an alpha-
00125 helix of an EntityView. The determination is more stable if there are at least
00126 4 residues on each side (8 is even better) of the proline around which the
00127 helix is kinked. The selection should contain all residues in the correct
00128 order and with no gaps and no missing C-alphas.
00129
00130 :param sele: A selection containing the alpha helix to be analyzed
00131 :type sele: :class:`~ost.mol.EntityView`
00132 :param proline: A selection containing only the proline (or another residue)
00133 around which the helix is kinked. If False, the proline will
00134 be searched for automatically
00135 :type proline: :class:`ost.mol.EntityView`
00136
00137 :return: A tuple (bend_angle, face_shift, wobble_angle).
00138 :rtype: (float, float, float)
00139 """
00140 (proline,proline_ca)=__FindProline(sele,proline)
00141 proline_num=proline.GetNumber().num
00142 (pre_proline,post_proline)=__SelectPreAndPostProline(sele,proline_num)
00143 (ca_3,ca_4)=__FindCa3AndCa4(sele,proline_ca,proline_num)
00144
00145 pre_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(pre_proline)
00146 post_proline_axis=ost.mol.alg.structure_analysis.CalculateHelixAxis(post_proline)
00147 prepa=pre_proline_axis.GetDirection()
00148 prepc=pre_proline_axis.GetOrigin()
00149 postpa=post_proline_axis.GetDirection()
00150 postpc=post_proline_axis.GetOrigin()
00151
00152 bend=__CalculateBendAngle(prepa,postpa)
00153 wobble=__CalculateWobbleAngle(prepa,postpa,postpc,proline_ca.pos)
00154 shift=__CalculateFaceShift(prepa,postpa,prepc,postpc,proline_ca.pos,ca_3.pos,ca_4.pos,bend)
00155 return (bend,shift,wobble)
00156
00157
00158
00159