简体   繁体   English

Numpy einsum()用于旋转网格

[英]Numpy einsum() for rotation of meshgrid

I have a set of 3d coordinates that was generated using meshgrid(). 我有一组使用meshgrid()生成的3d坐标。 I want to be able to rotate these about the 3 axes. 我希望能够绕3轴旋转它们。

I tried unraveling the meshgrid and doing a rotation on each point but the meshgrid is large and I run out of memory. 我尝试解开网格网并在每个点上进行旋转但是网格网格很大而且内存不足。

This question addresses this in 2d with einsum(), but I can't figure out the string format when extending it to 3d. 这个问题在2d中用einsum()解决了这个问题 ,但是在将它扩展到3d时我无法弄清楚字符串格式。

I have read several other pages about einsum() and its format string but haven't been able to figure it out. 我已经阅读了几个关于einsum()及其格式字符串的其他页面,但还没有弄清楚。

EDIT: 编辑:

I call my meshgrid axes X, Y, and Z, each is of shape (213, 48, 37). 我称我的网格轴X,Y和Z,每个都是形状(213,48,37)。 Also, the actual memory error came when I tried to put the results back into a meshgrid. 此外,当我试图将结果放回到meshgrid中时,出现了实际的内存错误。

When I attempted to 'unravel' it to do point by point rotation I used the following function: 当我试图“解开”它逐点旋转时,我使用了以下函数:

def mg2coords(X, Y, Z):
    return np.vstack([X.ravel(), Y.ravel(), Z.ravel()]).T

I looped over the result with the following: 我用以下方法循环结果:

def rotz(angle, point):
    rad = np.radians(angle)
    sin = np.sin(rad)
    cos = np.cos(rad)
    rot = [[cos, -sin, 0],
           [sin,  cos, 0],
           [0, 0, 1]]

    return np.dot(rot, point)

After the rotation I will be using the points to interpolate onto. 在旋转之后,我将使用点进行插值。

Working with your definitions: 使用您的定义:

In [840]: def mg2coords(X, Y, Z):
        return np.vstack([X.ravel(), Y.ravel(), Z.ravel()]).T

In [841]: def rotz(angle):
        rad = np.radians(angle)
        sin = np.sin(rad)
        cos = np.cos(rad)
        rot = [[cos, -sin, 0],
               [sin,  cos, 0],
               [0, 0, 1]]
        return np.array(rot)
        # just to the rotation matrix

define a sample grid: 定义一个示例网格:

In [842]: X,Y,Z=np.meshgrid([0,1,2],[0,1,2,3],[0,1,2],indexing='ij')    
In [843]: xyz=mg2coords(X,Y,Z)

rotate it row by row: 逐行旋转:

In [844]: xyz1=np.array([np.dot(rot,i) for i in xyz])

equivalent einsum row by row calculation: 等效的einsum逐行计算:

In [845]: xyz2=np.einsum('ij,kj->ki',rot,xyz)

They match: 他们匹配:

In [846]: np.allclose(xyz2,xyz1)
Out[846]: True

Alternatively I could collect the 3 arrays into one 4d array, and rotate that with einsum . 或者,我可以将3个阵列收集到一个4d阵列中,然后用einsum旋转它。 Here np.array adds a dimension at the start. 这里np.arraynp.array添加一个维度。 So the dot sum j dimension is 1st, and the 3d of the arrays follow: 因此, dotj维度为1,数组的3d如下:

In [871]: XYZ=np.array((X,Y,Z))
In [872]: XYZ2=np.einsum('ij,jabc->iabc',rot,XYZ)

In [873]: np.allclose(xyz2[:,0], XYZ2[0,...].ravel())
Out[873]: True

Similary for the 1 and 2 . 12相似。

Alternatively I could split XYZ2 into 3 component arrays: 或者,我可以将XYZ2分成3个组件数组:

In [882]: X2,Y2,Z2 = XYZ2
In [883]: np.allclose(X2,xyz2[:,0].reshape(X.shape))
Out[883]: True

Use ji instead of ij if you want to rotate in the other direction, ie use rot.T . 如果要沿另一个方向旋转,请使用ji而不是ij ,即使用rot.T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM