Python通过坐标系变换实现分子结构的平移和旋转

背景

在最近做的课题中需要将蛋白质靶点的圆柱形空腔展开,由于分子的坐标本身不是沿坐标轴展开的,因此处理起来异常的麻烦。以我浅薄的知识判断,把蛋白-配体形成的腔体的主轴放到x轴上,在在y-z方向上做极坐标展开应该是一个简单可行的方法。

在实现上,把主轴平移到x轴和直接把主轴作为x轴是等效的。然而这里面最shaib的地方在于,网上的很多教程写的乱七八糟,对数学不好的我来说那真是吃屎一样难受,因此自己简单做了做整理了一下。

坐标变换原理

这里主要参考这一篇博客,注意这里的逆矩阵计算有些问题
图形学1-三维坐标系间的变换矩阵推导.
简单点说,变换前后的坐标满足这些关系式:
在这里插入图片描述
其中(x0,y0,z0)是新坐标系的原点在原坐标系的坐标,(x,y,z)是要变换的点在原坐标系的坐标。其他的符号可以参考原博客。这些关系式建立了这样的联系:新坐标系下的坐标加上坐标原点的平移量(比如x0)等于原坐标。这样就可以得到:
在这里插入图片描述
这里我们暂时把这个4×4的矩阵称为T,显然原坐标和T-1的矢量积就是新坐标了。
因为numpy中的np.linalg.inv()已经帮我们解决了逆矩阵的问题,这里我们就不做推导了。

实现

在这里插入图片描述
体系的初始结构如上图所示。这里面首先要处理的问题是新坐标系的基向量的方向。这里我选择了1493和1495两个残基上的α碳的方向作为x轴,因为这两几个碳原子的结构比较稳定。随后选择1494号残基的α碳,把1494-αC和x轴的垂足的方向做y轴,把x轴、y轴的法向量做z轴。
垂足的计算可以参考这篇博客:三维空间:点到直线垂足坐标公式推导.
在确定了新的坐标轴后,计算矩阵并求逆,并将获得的矩阵和原坐标相乘即可。可以看到配体已经被移动到了新的坐标系的原点附近。
在这里插入图片描述

代码

整个流程的代码如下

#载入gro文件,这里我去除了水和离子,保存为dat格式
ResID,ResName,AtomName,x,y,z,OUTPUT = __readfile("sample.dat")

#找到1493和1495的α碳
a = []
for i in range(0,len(ResID)):
    if ResID[i] == 1493 and AtomName[i] == "CA" or ResID[i] == 1495 and AtomName[i] == "CA" :
        #print(ResName[i])
        a.append(i)
        #找到1494的α碳
    elif ResID[i] == 1494 and AtomName[i] == "CA":
        b = i

#把1493α碳记为x1,1495α碳记为x2,1494α碳记为x0
x1 = np.array((x[a[0]],y[a[0]],z[a[0]]))
x2 = np.array((x[a[1]],y[a[1]],z[a[1]]))
x0 = np.array((x[b],y[b],z[b]))
#获得第一个基向量u
u = x1-x2
#去取1493和1495的中点为新的坐标原点
P0 = ((x[a[0]]+x[a[1]])/2,(y[a[0]]+y[a[1]])/2,(z[a[0]]+z[a[1]])/2)

#计算垂足,公式太长分子分母分开写
fz = (x[a[1]]-x[b])*(x[a[0]]-x[a[1]])+ (y[a[1]]-y[b]) * (y[a[0]]-y[a[1]]) + (z[a[1]]-z[b])*(z[a[0]]-z[a[1]])
fm = (x[a[0]]-x[a[1]])*(x[a[0]]-x[a[1]])+ (y[a[0]]-y[a[1]])*(y[a[0]]-y[a[1]])+ (z[a[0]]-z[a[1]])*(z[a[0]]-z[a[1]])
k = -fz/fm
#Pn为垂足的坐标
Pn = ( k*(x[a[0]]-x[a[1]]) + x[a[1]] , k*(y[a[0]]-y[a[1]]) + y[a[1]] , k*(z[a[0]]-z[a[1]]) + z[a[1]] )
#垂足和1494碳的方向确定为新y轴,获得第二个基向量v
v = np.array(Pn) - np.array(x0)

#第三个基向量由u、v确定的平面计算得出
w = np.array([(u[1]*v[2]-v[1]*u[2]),(v[0]*u[2]-u[0]*v[2]),(u[0]*v[1]-v[0]*u[1])])

#基向量的长度等于1
u = u/np.linalg.norm(u)
v = v/np.linalg.norm(v)
w = w/np.linalg.norm(w)


#获得矩阵T
T = np.array([[u[0],u[1],u[2],P0[0]],
      [v[0],v[1],v[2],P0[1]],
      [w[0],w[1],w[2],P0[2]],
      [0,0,0,1]])

#获得逆矩阵
T_1 = np.linalg.inv(T)

#输出到gro文件
ff = open("test.gro","w")
print("Test File",file=ff)
print(" "+str(len(ResID)),file=ff)
for i in range(0,len(ResID)):
    coord0 = np.array([x[i],y[i],z[i],1])
    newcoord = np.dot(GG,coord0)#这里的计算的矢量积即为新坐标
    p1 = '%.3f' % newcoord[0]#gro文件取三位浮点数
    p2 = '%.3f' % newcoord[1]
    p3 = '%.3f' % newcoord[2]
    print(OUTPUT[i]+p1.rjust(8)+p2.rjust(8)+p3.rjust(8),file=ff)
print("  14.80330  11.16660  15.71149",file=ff)
ff.close()

对于只考虑坐标变换的同学,直接使用这个函数即可:

#输入:新坐标系的基向量u、v、w和新坐标原点P0
def TransfMatrix(u,v,w,P0):
    u = u/np.linalg.norm(u)
    v = v/np.linalg.norm(v)
    w = w/np.linalg.norm(w)
    T = np.array([[u[0],u[1],u[2],P0[0]],
          [v[0],v[1],v[2],P0[1]],
          [w[0],w[1],w[2],P0[2]],
          [0,0,0,1]])
    return np.linalg.inv(T)
#输出坐标系变换矩阵
#注意顺序!!
NewCoord = np.dot(T_1,OriginCoord)
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Python中,我们可以使用各种库和函数来进行三维坐标的平移旋转操作。 首先,我们可以使用NumPy库来处理三维坐标和向量的运算。NumPy提供了功能强大的数组和矩阵操作函数,适用于处理复杂的三维坐标变换。 对于平移操作,可以通过将所有坐标点的x、y、z值分别增加指定的平移量来实现。例如,如果要将所有坐标点沿x轴平移2个单位,则可以使用以下代码: ```python import numpy as np # 定义要平移的三维坐标 coords = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 定义平移向量 translation = np.array([2, 0, 0]) # 执行平移操作 translated_coords = coords + translation print(translated_coords) ``` 对于旋转操作,可以使用scipy库中的旋转函数。scipy包含了旋转函数,可以通过指定旋转轴、旋转角度和旋转中心来实现三维坐标的旋转。 例如,如果要沿着z轴旋转45度,可以使用以下代码: ```python import numpy as np from scipy.spatial.transform import Rotation # 定义要旋转的三维坐标 coords = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 定义旋转角度(弧度) angle = np.pi/4 # 定义旋转轴 axis = np.array([0, 0, 1]) # 定义旋转中心 center = np.array([0, 0, 0]) # 创建旋转对象 rotation = Rotation.from_rotvec(angle * axis) # 执行旋转操作 rotated_coords = rotation.apply(coords - center) + center print(rotated_coords) ``` 以上代码使用了scipy库中的Rotation类来实现旋转操作。首先,我们定义旋转角度、旋转轴和旋转中心,然后使用from_rotvec函数创建旋转对象,最后使用apply函数应用旋转操作。 通过以上代码,我们可以在Python实现三维坐标的平移旋转操作。请注意,以上代码仅是示例,实际应用中可能需要根据具体需求进行调整和修改。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值