[英]write a python code the most efficient way
I am writing a code using a Python library MDAnalysis. 我正在使用Python库MDAnalysis编写代码。 And I have an array (502,3) of atom positions I want to get an array of bonds (vectors of position of Atom(i+1) - Atom(i)) And then I want to obtain an average tensor qab = which is essentially a np.outer(ua,ub) averaged by all atoms.
我有一个原子位置的数组(502,3)我想获得一个键数组(Atom(i + 1)的位置向量 - 原子(i))然后我想得到一个平均张量qab =本质上是所有原子平均的np.outer(ua,ub)。
I can rewrite this code using fortran subroutines but I think it would be more pleasing to see a delicious numpy slicing solution:) Here is my code that I wrote and that works, I want to make it faster and prettier. 我可以使用fortran子程序重写这段代码,但我认为看到一个美味的numpy切片解决方案会更令人愉快:)这是我编写的代码,这是有效的,我想让它变得更快更漂亮。 Thank you in advance for your help.
预先感谢您的帮助。
bb = u.selectAtoms("all")
coor = bb.positions
print coor.shape # return is (502,3)
# the coordinates of the atoms that we split on 3 dimensions
bbx = coor[:,0]
bby = coor[:,1]
bbz = coor[:,2]
#the bond vectors we obtain by subtructing atoms positions
bbx_ave = bbx[:-1] - bbx[1:]
bby_ave = bby[:-1] - bby[1:]
bbz_ave = bbz[:-1] - bbz[1:]
#now we concentrate everything back so we have one big array
bb_res = np.vstack((bbx_ave, bby_ave, bbz_ave))
# print bb_res.shape # the return is (3,501)
# now we have an array of bonds
# qab - the result tensor which we want to get
nq = len(bb_res)
qab = np.zeros((3,3))
count = 0.
for i in xrange(0, nq):
for j in xrange(0, i+1):
qab = qab + np.outer(bb_res[:,i], bb_res[:,j])
count += 1.
qab = qab/count
print qab
[[ 0.21333394 0.5333341 0. ]
[ 0.5333341 4. 0. ]
[ 0. 0. 0. ]]
I've done my best below. 我在下面做了最好的。 It's pretty easy to generate your
bb_res
more efficiently, but I was unable to optimize the double for
loop. 生成
bb_res
非常容易,但是我无法优化double for
循环。 On my computer, my method is about 26% faster. 在我的电脑上,我的方法快了大约26%。 Also based on the statement of your question I believe there is a bug in your code which I pointed out in a comment.
同样基于您的问题陈述,我相信您的代码中存在一个错误,我在评论中指出了这个错误。 I have fixed this bug in my answer, so it produces a slightly different output than your code.
我已在我的答案中修复了这个错误,因此它产生的输出与您的代码略有不同。
import numpy as np
from numpy.random import rand
# create some mock data
coor = rand(502,3)
def qab(coor):
# this is the transpose of your bb_res
# transposing is as simple as bb_res.T
bb_res = coor[:-1] - coor[1:]
nq = bb_res.shape[1]
out = np.zeros((3,3))
for i in xrange(0, nq):
for j in xrange(0, i):
tmp = np.outer(bb_res[i], bb_res[j])
out += tmp + tmp.T
out += np.outer(bb_res[i], bb_res[i])
return out / nq**2
print qab(coor)
Assuming you meant nq = bb_res.shape[1]
in your code snippet, I can reproduce the output with the following vectorized code: 假设您的代码片段中的
nq = bb_res.shape[1]
,我可以使用以下向量化代码重现输出:
d = np.diff(coor, axis=0)
I, J = np.triu_indices(d.shape[0])
print np.dot(d[J].T, d[I]) / len(J)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.