使用numpy计算分子内坐标
技术背景
当我们打开一个用于表示分子构象的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对数组进行滚动之后做减法,最后再去掉一个结果。事实上用前面的这种算法会更加简单高效一些。
# inner_crd.py
import numpy as np
np.random.seed(1)
EPSILON = 1e-08
def get_vec(crd):
""" Get the vector of the sequential coordinate.
"""
# (B, A, D)
crd_ = np.roll(crd, -1, axis=-2)
vec = crd_ - crd
# (B, A-1, D)
return vec[:, :-1, :]
def get_dis(crd):
""" Get the distance of the sequential coordinate.
"""
# (B, A-1, D)
vec = get_vec(crd)
# (B, A-1, 1)
dis = np.linalg.norm(vec, axis=-1, keepdims=True)
return dis, vec
def get_angle(crd):
""" Get the bond angle of the sequential coordinate.
"""
# (B, A-1, 1), (B, A-1, D)
dis, vec = get_dis(crd)
vec_ = np.roll(vec, -1, axis=-2)
dis_ = np.roll(dis, -1, axis=-2)
# (B, A-1, 1)
angle = np.einsum('ijk,ijk->ij', vec, vec_)[..., None] / (dis * dis_ + EPSILON)
# (B, A-2, 1), (B, A-1, 1), (B, A-1, D)
return np.arccos(angle[:, :-1, :]), dis, vec
def get_dihedral(crd):
""" Get the dihedrals of the sequential coordinate.
"""
# (B, A-2, 1), (B, A-1, 1), (B, A-1, D)
angle, dis, vec_0 = get_angle(crd)
# (B, A-1, D)
vec_1 = np.roll(vec_0, -1, axis=-2)
vec_2 = np.roll(vec_1, -1, axis=-2)
vec_01 = np.cross(vec_0, vec_1)
vec_12 = np.cross(vec_1, vec_2)
vec_01 /= np.linalg.norm(vec_01, axis=-1, keepdims=True) + EPSILON
vec_12 /= np.linalg.norm(vec_12, axis=-1, keepdims=True) + EPSILON
# (B, A-1, 1)
dihedral = np.einsum('ijk,ijk->ij', vec_01, vec_12)[..., None]
# (B, A-3, 1), (B, A-2, 1), (B, A-1, 1)
return np.arccos(dihedral[:, :-2, :]), angle, dis
def get_inner_crd(crd):
""" Concat the distance, angles and dihedrals to get the inner coordinate.
"""
# (B, A-3, 1), (B, A-2, 1), (B, A-1, 1)
dihedral, angle, dis = get_dihedral(crd)
# (B, A, 1)
dihedral_ = np.pad(dihedral, ((0, 0), (3, 0), (0, 0)), mode='constant', constant_values=0)
angle_ = np.pad(angle, ((0, 0), (2, 0), (0, 0)), mode='constant', constant_values=0)
dis_ = np.pad(dis, ((0, 0), (1, 0), (0, 0)), mode='constant', constant_values=0)
# (B, A, 3)
inner_crd = np.concatenate((dis_, angle_, dihedral_), axis=-1)
return inner_crd
if __name__ == '__main__':
B = 1
A = 6
D = 3
# (B, A, D)
origin_crd = np.random.random((B, A, D))
# (B, A, 3)
icrd = get_inner_crd(origin_crd)
print (icrd)
上述代码执行的输出结果如下所示:
[[[0. 0. 0. ]
[0.59214856 0. 0. ]
[0.38167145 1.89801242 0. ]
[0.46143538 1.2138982 1.46589893]
[0.86899521 2.32255675 1.61009033]
[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
参考链接
使用numpy计算分子内坐标的更多相关文章
- numpy计算路线距离
numpy计算路线距离 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 enumerate遍历数组 np.diff函数 numpy适用数组作为索引 标记路线上的点 \[X={X1,X ...
- php计算两个坐标(经度,纬度)之间距离的方法
本文实例讲述了php计算两个坐标(经度,纬度)之间距离的方法.分享给大家供大家参考.具体如下: 这里使用php计算两个坐标(经度,纬度)之间的距离,返回结果为米或者千米 function distan ...
- HTML5地理定位(已知经纬度,计算两个坐标点之间的距离)
事实上,地球上任意两个坐标点在地平线上的距离并不是直线,而是球面的弧线. 下面介绍如何利用正矢公式计算已知经纬度数据的两个坐标点之间的距离.半正矢公式也成为Haversine公式,它最早时航海学中的重 ...
- numpy计算数组中满足条件的个数
Numpy计算数组中满足条件元素个数 需求:有一个非常大的数组比如1亿个数字,求出里面数字小于5000的数字数目 1. 使用numpy的random模块生成1亿个数字 2. 使用Python原生语法实 ...
- python计算非内置数据类型占用内存
getsizeof的局限 python非内置数据类型的对象无法用sys.getsizeof()获得真实的大小,例: import networkx as nx import sys G = nx.Gr ...
- 计算4000000000内的最大f(n)=n值---字符串的问题python实现(五岁以下儿童)
问题: 写一个函数,计算4 000 000 000 以内的最大的那个f(n)=n的值,函数f的功能是统计全部0到n之间全部含有数字1的数字和.比方:f(13)= 6,由于"1"在& ...
- iOS 计算两个坐标之间的距离
//第一个坐标 CLLocation *before=[[CLLocation alloc] initWithLatitude:29.553968 longitude:106.538872]; //第 ...
- python中numpy计算数组的行列式numpy.linalg.det()
numpy.linalg.det numpy.linalg.det(a)[source] 计算任何一个数组a的行列式,但是这里要求数组的最后两个维度必须是方阵. 参数: a : (..., M, M) ...
- 用numpy计算成交量加权平均价格(VWAP),并实现读写文件
VWAP(Volume-Weighted Average Price,成交量加权平均价格)是一个非常重要的经济学量,它代表着金融资产的“平均”价格.某个价格的成交量越高,该价格所占的权重就越大.VWA ...
- poj 1265 Area【计算几何:叉积计算多边形面积+pick定理计算多边形内点数+计算多边形边上点数】
题目:http://poj.org/problem?id=1265 Sample Input 2 4 1 0 0 1 -1 0 0 -1 7 5 0 1 3 -2 2 -1 0 0 -3 -3 1 0 ...
随机推荐
- flutter ui---->一些类QQ的实现
整理一下比较有意思的类QQ的UI实现.Nothing that has meaning is easy. Easy doesn't enter into grown-up life. darken t ...
- JetBrains 2022全家桶-激活
## JetBrains 全家桶 激活教程 https://tech.souyunku.com/?page_id=50199
- TS 基础及在 Vue 中的实践:TypeScript 都发布 5.0 版本啦,现在不学更待何时!
大家好,我是 Kagol,OpenTiny 开源社区运营,TinyVue 跨端.跨框架组件库核心贡献者,专注于前端组件库建设和开源社区运营. 微软于3月16日发布了 TypeScript 5.0 版本 ...
- SQL Server修改sa用户密码
SQL Server数据库使用windows用户登录,安全性->登录名->找到sa用户->属性: 可直接修改sa用户密码(可去掉勾选强制实施密码策略)
- 生产事故-记一次特殊的OOM排查
入职多年,面对生产环境,尽管都是小心翼翼,慎之又慎,还是难免捅出篓子.轻则满头大汗,面红耳赤.重则系统停摆,损失资金.每一个生产事故的背后,都是宝贵的经验和教训,都是项目成员的血泪史.为了更好地防范和 ...
- 四月十八日java基础知识
1.由于每个对象的pi值都是相同的,所以没有必要让每个对象都保存有自己的pi值,因此将pi声明为静态变量,使之成为所有对象共用的存储空间,所有对象都公用pi这个变量也就是说共用的变量可以设定为静态变量 ...
- .NET Core MongoDB数据仓储和工作单元模式实操
前言 上一章节我们主要讲解了MongoDB数据仓储和工作单元模式的封装,这一章节主要讲的是MongoDB用户管理相关操作实操.如:获取所有用户信息.获取用户分页数据.通过用户ID获取对应用户信息.添加 ...
- 从零开始学Vue(二~三)—— Vue 实例 / 模板语法(插值、指令)
概述 vue.js作为现在笔记热门的JS框架,使用比较简单易上手,也成为很多公司首选的JS框架. 但是对于初学者可能学起来有些麻烦,所以推出<从零开始学Vue>系列博客,本系列计划推出19 ...
- 帝国cms随机sql语句,mysql高效的随机查询
select * from AppleStorewhere rand()<0.015limit 100;
- Swift Codable协议实战:快速、简单、高效地完成JSON和Model转换!
前言 Codable 是 Swift 4.0 引入的一种协议,它是一个组合协议,由 Decodable 和 Encodable 两个协议组成.它的作用是将模型对象转换为 JSON 或者是其它的数据格式 ...