7

そのため、ソフトウェアでかなり大きなボトルネックに遭遇しました。cords各行が座標に対応する座標のセットがありX,Y,Zます。の各座標にcordsは、 で定義された領域がありatom_projます。変数はatoms変数に対応し、cordsにキーを提供しますatom_proj

座標をgrid配列に投影してから回転させ、回転数が満たされるまで繰り返します。Y を無視して、X 座標と Z 座標のみを投影します。

以下のコードの簡略化されたバージョンがあります。小さな座標セットと回転数の場合、コードは比較的高速に実行されます。ただし、座標セットと回転リストの両方が大きい場合は、時間がかかることがあります。座標の数は、数百から数万までさまざまです。gridヒート マップを作成するために、その領域を一定数または回転させて投影します。座標セットのヒート マップの例も以下に示します。

質問:

(i) - 座標の行列への投影時間を短縮するにはどうすればよいですか

grid(ii) -配列スプライシングではなく座標領域を適用するより Pythonic な方法はありますか?

import numpy as np
cords = np.array([[5,4,5],[5,4,3],[6,4,6]])
atoms = np.array([['C'],['H'],['C']])
atom_proj = {'H':np.array([[0,0,0,0,0],[0,0,1,0,0],[0,1,1,1,0],[0,0,1,0,0],[0,0,0,0,0]]),'C':np.array([[0,0,0,0,0,0,0],[0,0,0,0,0,0,0],[0,0,1,1,1,0,0],[0,0,1,1,1,0,0],[0,0,1,1,1,0,0],[0,0,0,0,0,0,0],[0,0,0,0,0,0,0]])}

grid = np.zeros((10,10))

for rot in xrange(1,10): 
    # This for loop would contain a list of list of rotations to apply which are calculated before hand.
    # apply rotation
    for values in zip(cords, atoms):
        atom_shape = np.shape(atom_proj[values[1][0]])
        rad = (atom_shape[0]-1)/2                                
        grid[values[0][2]-rad:values[0][2]+rad+1,values[0][0]-rad:values[0][0]+rad+1] += atom_proj[values[1][0]]    
print grid

ヒートマップ: ここに画像の説明を入力

4

1 に答える 1

4

このようなものは、内側のループで機能するはずです

extruded = np.zeros((N, 10,10))
extruded[range(N), cords[:,2], cords[:,0]] = 1

grid = np.zeros((10,10))
for atom, proj in atom_proj.iteritems():
    centers = extruded[atoms==atom].sum(0)
    projected = nd.convolve(centers, proj)
    grid += projected

いくつかのメモ:

  • まだループがありますが、個々のアトムの長さの配列では2なく、アトム タイプの長さの配列を使用しています。N
  • for rot in []ここでは何もしていないので、ループを省略しましたが、うまく収まるはずです。
  • これは、グリッドのスタック内の各原子の中心位置に 1 を配置することで機能します。次に、原子タイプごとに、それらがすべて追加されます。次に、@Joe が示唆したように、原子射影はそれらの中心で畳み込まれます。
  • テストのために、私atomsは 1d、あなたは 2d です。これが意図的であったかどうかはわかりません。
  • 以下に、3番目のバージョンも追加しました。これはあなたのアルゴリズムですが、私が理解できた変数を使用すると、OP_simplified

完全なスイートは次のとおりです。

import numpy as np
import scipy.ndimage as nd

N = 1000
cords = np.random.randint(3, 7, (N, 3)) #np.array([[5,4,5],[5,4,3],[6,4,6]])
atoms = np.random.choice(list('HC'), N) #np.array([['C'],['H'],['C']])
atom_proj = {'H': np.array([[0,0,0,0,0],
                            [0,0,1,0,0],
                            [0,1,1,1,0],
                            [0,0,1,0,0],
                            [0,0,0,0,0]]),
             'C': np.array([[0,0,0,0,0,0,0],
                            [0,0,0,0,0,0,0],
                            [0,0,1,1,1,0,0],
                            [0,0,1,1,1,0,0],
                            [0,0,1,1,1,0,0],
                            [0,0,0,0,0,0,0],
                            [0,0,0,0,0,0,0]])}

def project_atom(cords, atoms, atom_proj):
    extruded = np.zeros((N, 10,10))
    extruded[range(N), cords[:,2], cords[:,0]] = 1
    grid = np.zeros((10,10))
    for atom, proj in atom_proj.iteritems():
        grid += nd.convolve(extruded[atoms.squeeze()==atom].sum(0), proj, mode='constant')
    return grid

def OP_simplified(cords, atoms, atom_proj):
    rads = {atom: (proj.shape[0] - 1)/2 for atom, proj in atom_proj.iteritems()}
    grid = np.zeros((10,10))
    for (x,y,z), atom in zip(cords, atoms):
        rad = rads[atom]
        grid[z-rad:z+rad+1, x-rad:x+rad+1] += atom_proj[atom]
    return grid

def OP(cords, atoms, atom_proj):
    grid = np.zeros((10,10))
    for values in zip(cords, atoms):
        atom_shape = np.shape(atom_proj[values[1][0]])
        rad = (atom_shape[0]-1)/2
        grid[values[0][2]-rad:values[0][2]+rad+1,values[0][0]-rad:values[0][0]+rad+1] += atom_proj[values[1][0]]
    return grid

できます!

In [957]: np.allclose(OP(cords, atoms, atom_proj), project_atom(cords, atoms, atom_proj))
Out[957]: True

そしてタイミング:

In [907]: N = 1000

In [910]: timeit OP(cords, atoms, atom_proj)
10 loops, best of 3: 30.7 ms per loop

In [911]: timeit project_atom(cords, atoms, atom_proj)
100 loops, best of 3: 2.97 ms per loop

In [913]: N = 10000

In [916]: timeit project_atom(cords, atoms, atom_proj)
10 loops, best of 3: 33.3 ms per loop

In [917]: timeit OP(cords, atoms, atom_proj)
1 loops, best of 3: 314 ms per loop
于 2013-11-06T16:31:41.507 に答える