基于截止距离,我想创建一个点列表,这些点是给定点的邻居。我遇到了如何将点的ID添加到numpy数组中。
我在如下所示的numpy数组中读取'坐标':
ID x y z
1. 1 1 0.000000 3.078000 0.554000
2. 2 0.000000 3.078000 2.170000
3. 3 2.666000 1.539000 0.554000
4. 4 2.666000 1.539000 2.170000
5. 5 1.774000 0.000000 3.324000
6. 6 2.712000 0.000000 7.207000
依旧......
我想要像这样的输出列表
ID neighbor1 neighbor2 ....neighbor5
1. 1 4 5 6 8
2. 2 1 4 6 n/a
3. 3 5 1 n/a 2
4. etc.
所以每个位置(1,2,3,4 ......等等)最多可以有5个邻居,如果小于5,我想把n / a放在那里。到目前为止,我有以下代码。
#neighborlist
flist = glob.glob(filename)
for f in flist:
load = np.loadtxt(f, usecols=(2,3,4))
coordinate=np.array(load)
s = (len(coordinate),6)
Nlist = np.zeros(s)
rcut = 2.5 #cutoff distance for neighbors
for f in flist:
load = np.loadtxt(f, usecols=(2,3,4))
coordinate=np.array(load)
for i in range(len(coordinate)):
idx = [i,]
for j in range(len(coordinate)):
if np.linalg.norm(coordinate[i]-coordinate[j]) < rcut and np.linalg.norm(coordinate[i]-coordinate[j]) > 0.1:
idx.append(j)
else:
idx = idx
while len(idx)<6:
idx.append('n/a')
print idx
Nlist[i,:]=idx
print Nlist
为此我得到了:
ValueError:无法将字符串转换为float:n / a
因为我已将Nlist
数组大小修复为(len(data),6)
,所以当邻居小于5(第一个元素是点本身)时,它不能复制Nlist[i,:]=idx
。在这种情况下,有没有办法动态声明Nlist
或使其大小变量?我知道这是一个棘手的问题,但必须解决这个问题。提前谢谢。
答案 0 :(得分:1)
可以这样做:
import numpy as np
from collections import defaultdict
coordinate = np.array([[0. , 3.078, 0.554],
[ 0. , 3.078, 2.17 ],
[ 2.666, 1.539, 0.554],
[ 2.666, 1.539, 2.17 ],
[ 1.774, 0. , 3.324],
[ 2.712, 0. , 7.207]])
rcut = 2.5
neighbors = defaultdict(list)
for ID1, ID2 in itertools.permutations(range(len(coordinate)), 2):
if np.linalg.norm(coordinate[ID1]-coordinate[ID2]) < rcut:
neighbors[ID1].append(ID2)
else:
neighbors[ID1].append('n/a')
for ID in neighbors:
print ID, neighbors[ID]
输出:
0 [1, 'n/a', 'n/a', 'n/a', 'n/a']
1 [0, 'n/a', 'n/a', 'n/a', 'n/a']
2 ['n/a', 'n/a', 3, 'n/a', 'n/a']
3 ['n/a', 'n/a', 2, 4, 'n/a']
4 ['n/a', 'n/a', 'n/a', 3, 'n/a']
5 ['n/a', 'n/a', 'n/a', 'n/a', 'n/a']
请注意,我使用字典输出,在我看来比列表更有意义。由于您的代码不读取ID,但将行号作为ID,我也是这样做的。当numpy开始编号为0时,ID从0开始。
另请注意,您的代码只会评估文件列表中的最后一个文件,因为您会覆盖您阅读的每个文件的坐标数组。
为什么要在输出中存储'n / a'而不是简单地为不同的ID设置不同长度的列表?
另请注意,我建议的代码效率不高。您可以使用cell lists等算法来加快速度。
如果你想有效地找到邻居,你可能也会对scipy.spatial模块感兴趣:
from scipy import spatial
kdtree = sp.spatial.KDTree(coordinate)
kdtree.query_pairs(rcut)
输出:
{(0, 1), (2, 3), (3, 4)}
这将为您提供距离小于rcut的所有点对。这是构建所需输出列表所需的基本信息。