经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » NumPy » 查看文章
使用numpy计算分子内坐标
来源:cnblogs  作者:DECHIN  时间:2023/6/9 11:22:03  对本文有异议

技术背景

当我们打开一个用于表示分子构象的xyz文件或者pdb文件,很容易可以理解这种基于笛卡尔坐标的空间表征方法。但是除了笛卡尔坐标表示方法之外,其实也有很多其他的方法用于粗粒化或者其他目的的表征方法,比如前一篇文章中所介绍的在AlphaFold2中所使用的残基的刚体表示方法。而这种刚体坐标,在本质上来说也是一种特殊的分子内坐标表示方法,因为对于每一个残基而言只有旋转和平移的自由度,而残基内部是保持互相之间相对静止的。换句话说,每一个残基的内坐标是保持不变的,本文主要介绍分子的内坐标表示方法。

具体表示方法

在笛卡尔坐标系中,我们使用绝对坐标来表示每一个原子的空间位置,虽然也可以用于计算分子之间的相对位置,但是如果每一次更新之后都需要重新计算一遍这个相对位置的话,在演化效率上来说会比较低。因此,我们考虑有没有一种方法,可以直接对分子的“相对位置”进行演化,直到演化结束之后,再转化回笛卡尔坐标进行可视化。其实,市面上已经有一些软件可以直接可视化这种基于“相对位置”的内坐标了,这里我们主要探讨从绝对坐标到相对坐标的算法。

  • 绝对坐标描述的是B个体系,每个体系A个原子的三维空间坐标\(\textbf{r}_i\),在python编程中我们可以用张量的维度来描述这个三维坐标(B, A, D)。
  • 相对坐标的第一个参量是原子之间的距离\(l_{i,i+1}\),其张量维度为(B, A-1, 1)。
  • 相对坐标的第二个参量是原子之间的夹角\(a_{i,i+1,i+2}\),其张量维度为(B, A-2, 1)。
  • 相对坐标的第三个参量是原子之间的二面角\(d_{i,i+1,i+2,i+3}\),其张量维度为(B, A-3, 1)。

最后在计算得到所有的内坐标参量之后,我们可以用concat的方法把它们按照最后一个维度进行拼接,并且在原子数维度进行扩展,最终得到一个(B, A, 3)的张量,也就是我们所需要的最终的内坐标。

代码实现

其实这个算法逻辑是很简单的,我们更多的注重一个原生算子的使用以及代码的复用。以下是几个相关的关注点:

  • 在计算距离、角度和二面角的过程中,我们都会使用到序列原子之间的相对矢量(B, A-1, D),那么在计算过一次之后我们应该保存下来以供几个不同的函数使用。
  • 在numpy或者是一些常用的深度学习框架中,我们最好在代码实现阶段就去避免\(\frac{x}{0}\)这种情况的出现,一般在遇到除法、反三角函数或者对数函数的时候,我们可以在对应的位置加一个小量\(\epsilon=1e-08\)以避免出现nan的情况。
  • 在计算相对矢量的时候我们一般使用的是错位相减,比如可以使用crd[1:]-crd[:-1],但是这里我们在计算过程中使用的是numpy.roll对数组进行滚动之后做减法,最后再去掉一个结果。事实上用前面的这种算法会更加简单高效一些。
  1. # inner_crd.py
  2. import numpy as np
  3. np.random.seed(1)
  4. EPSILON = 1e-08
  5. def get_vec(crd):
  6. """ Get the vector of the sequential coordinate.
  7. """
  8. # (B, A, D)
  9. crd_ = np.roll(crd, -1, axis=-2)
  10. vec = crd_ - crd
  11. # (B, A-1, D)
  12. return vec[:, :-1, :]
  13. def get_dis(crd):
  14. """ Get the distance of the sequential coordinate.
  15. """
  16. # (B, A-1, D)
  17. vec = get_vec(crd)
  18. # (B, A-1, 1)
  19. dis = np.linalg.norm(vec, axis=-1, keepdims=True)
  20. return dis, vec
  21. def get_angle(crd):
  22. """ Get the bond angle of the sequential coordinate.
  23. """
  24. # (B, A-1, 1), (B, A-1, D)
  25. dis, vec = get_dis(crd)
  26. vec_ = np.roll(vec, -1, axis=-2)
  27. dis_ = np.roll(dis, -1, axis=-2)
  28. # (B, A-1, 1)
  29. angle = np.einsum('ijk,ijk->ij', vec, vec_)[..., None] / (dis * dis_ + EPSILON)
  30. # (B, A-2, 1), (B, A-1, 1), (B, A-1, D)
  31. return np.arccos(angle[:, :-1, :]), dis, vec
  32. def get_dihedral(crd):
  33. """ Get the dihedrals of the sequential coordinate.
  34. """
  35. # (B, A-2, 1), (B, A-1, 1), (B, A-1, D)
  36. angle, dis, vec_0 = get_angle(crd)
  37. # (B, A-1, D)
  38. vec_1 = np.roll(vec_0, -1, axis=-2)
  39. vec_2 = np.roll(vec_1, -1, axis=-2)
  40. vec_01 = np.cross(vec_0, vec_1)
  41. vec_12 = np.cross(vec_1, vec_2)
  42. vec_01 /= np.linalg.norm(vec_01, axis=-1, keepdims=True) + EPSILON
  43. vec_12 /= np.linalg.norm(vec_12, axis=-1, keepdims=True) + EPSILON
  44. # (B, A-1, 1)
  45. dihedral = np.einsum('ijk,ijk->ij', vec_01, vec_12)[..., None]
  46. # (B, A-3, 1), (B, A-2, 1), (B, A-1, 1)
  47. return np.arccos(dihedral[:, :-2, :]), angle, dis
  48. def get_inner_crd(crd):
  49. """ Concat the distance, angles and dihedrals to get the inner coordinate.
  50. """
  51. # (B, A-3, 1), (B, A-2, 1), (B, A-1, 1)
  52. dihedral, angle, dis = get_dihedral(crd)
  53. # (B, A, 1)
  54. dihedral_ = np.pad(dihedral, ((0, 0), (3, 0), (0, 0)), mode='constant', constant_values=0)
  55. angle_ = np.pad(angle, ((0, 0), (2, 0), (0, 0)), mode='constant', constant_values=0)
  56. dis_ = np.pad(dis, ((0, 0), (1, 0), (0, 0)), mode='constant', constant_values=0)
  57. # (B, A, 3)
  58. inner_crd = np.concatenate((dis_, angle_, dihedral_), axis=-1)
  59. return inner_crd
  60. if __name__ == '__main__':
  61. B = 1
  62. A = 6
  63. D = 3
  64. # (B, A, D)
  65. origin_crd = np.random.random((B, A, D))
  66. # (B, A, 3)
  67. icrd = get_inner_crd(origin_crd)
  68. print (icrd)

上述代码执行的输出结果如下所示:

  1. [[[0. 0. 0. ]
  2. [0.59214856 0. 0. ]
  3. [0.38167145 1.89801242 0. ]
  4. [0.46143538 1.2138982 1.46589893]
  5. [0.86899521 2.32255675 1.61009033]
  6. [0.84368274 2.92999231 1.97853456]]]

这个结果就是我们所需要的分子内坐标。

总结概要

本文主要介绍了在numpy的框架下实现的分子内坐标的计算,类似的方法可以应用于MindSpore和Pytorch、Jax等深度学习相关的框架中。分子的内坐标,可以更加直观的描述分子内的相对运动,通过键长键角和二面角这三个参数。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/inner_crd.html

作者ID:DechinPhy

更多原著文章请参考:https://www.cnblogs.com/dechinphy/

打赏专用链接:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

腾讯云专栏同步:https://cloud.tencent.com/developer/column/91958

CSDN同步链接:https://blog.csdn.net/baidu_37157624?spm=1008.2028.3001.5343

51CTO同步链接:https://blog.51cto.com/u_15561675

参考链接

  1. https://zhuanlan.zhihu.com/p/438712498#:~:text=而内坐标通过分子中各原子 相对位置,来确定原子位置,因此只要选定参考原子,内坐标系下的分子坐标天生满足旋转平移不变性。 分子中全部原子的内坐标总称为“Z-矩阵” (Z-matrix)。

原文链接:https://www.cnblogs.com/dechinphy/p/inner_crd.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号