Replace matrix @ vector list comprehensions with something more efficient I'm looking to replace list comprehensions like the following with something more efficient and I was wondering if numpy can be used.

[obj.matrix_world @ v.co for v in obj.data.vertices]


I can do this, which is significantly faster, but still lacks the matrix multiplication, that needs to happen for each coordinate.

coords = np.empty((len(obj.data.vertices), 3), 'f')
obj.data.vertices.foreach_get('co', np.reshape(coords, len(obj.data.vertices) * 3))


I was hoping it would just be

np.matrix(obj.matrix_world) @ coords


But that fails with (FWIW, It's just a cube, hence (8, 3))

ValueError: shapes (4,4) and (8,3) not aligned: 4 (dim 1) != 8 (dim 0)


Similarly, doing 

for co in coords:
    np.matrix(obj.matrix_world) @ co


fails with

ValueError: shapes (4,4) and (3,) not aligned: 4 (dim 1) != 3 (dim 0)


So I've hit a wall now. Numpy can't multiply a 4x4 matrix with a 3d vector, but Blender can. How do I solve this in a numpy way?



edit:

Based on @JoseConseco's excellent reply below, this is what I'm doing now

mx = active.matrix_world
verts = active.data.vertices
vert_count = len(verts)

coords = np.empty((vert_count, 3), 'f')
verts.foreach_get('co', np.reshape(coords, vert_count * 3))

coords_4d = np.ones((vert_count, 4), 'f')
coords_4d[:, :-1] = coords

coords = np.einsum('ij,aj-&gt;ai', mx, coords_4d)[:, :-1]


Note, that there's no need to convert the (mathutils) Matrix into an np array. It works fine just like that.

Based on my tests, doing this via numpy is ~3 times faster than the list comprehension.
Quickest way AFAIK:

mat = np.array(self.curveObj.matrix_world)

verts_co = np.zeros((vertCount*3), dtype=np.float)
mesh.vertices.foreach_get("co", verts_co)
verts_co.shape = (vertCount, 3)
verts_co_4d = np.ones(shape=(vertCount, 4), dtype=np.float)
verts_co_4d[:, :-1] = verts_co  # cos v (x,y,z,1) - point,   v(x,y,z,0)- vector
splinePoints_world = np.einsum('ij,aj-&gt;ai', mat, splinePoints)