I have a 3D numpy array A of shape (2133, 3, 3). Basically this is a list of 2133 lists with three 3D points. Furthermore I have a function which takes three 3D points and returns one 3D point, x = f(a, b, c), with a, b, c, x numpy arrays of length 3. Now I want to apply f to A, so that the output is an array of shape (2133, 3). So something like numpy.array([f(*A[0]),...,f(*A[2132])).
I tried numpy.apply_along_axis and numpy.vectorize without success.
To be more precise the function f I consider is given by:
def f(a, b, c, r1, r2=None, r3=None):
a = np.asarray(a)
b = np.asarray(b)
c = np.asarray(c)
if np.linalg.matrix_rank(np.matrix([a, b, c])) != 3:
# raise ValueError('The points are not collinear.')
return None
a, b, c, = sort_triple(a, b, c)
if any(r is None for r in (r2, r3)):
r2, r3 = (r1, r1)
ex = (b - a) / (np.linalg.norm(b - a))
i = np.dot(ex, c - a)
ey = (c - a - i*ex) / (np.linalg.norm(c - a - i*ex))
ez = np.cross(ex, ey)
d = np.linalg.norm(b - a)
j = np.dot(ey, c - a)
x = (pow(r1, 2) - pow(r2, 2) + pow(d, 2)) / (2 * d)
y = ((pow(r1, 2) - pow(r3, 2) + pow(i, 2) + pow(j, 2)) / (2*j)) - ((i/j)*x)
z_square = pow(r1, 2) - pow(x, 2) - pow(y, 2)
if z_square >= 0:
z = np.sqrt(z_square)
intersection = a + x * ex + y*ey + z*ez
return intersection
A = np.array([[[131.83, 25.2, 0.52], [131.51, 22.54, 0.52],[133.65, 23.65, 0.52]], [[13.02, 86.98, 0.52], [61.02, 87.12, 0.52],[129.05, 87.32, 0.52]]])
r1 = 1.7115
np.vectorizeandnp.apply_along_axiswould be helpful. Also, what exactly does the function f do? You might be able to replace it with a vectorized version.f. I think the problem withnp.apply_along_axisis that it is applied to a 1D-slice along the given axis.np.vectorizedoes not work because the unpacking is not done in the correct way. Even if I rewritef, so that it takes an array of shape (3,3), how do I tell numpy to iterate over the first axis and take the 3x3 subarrays?fin a way that it works with arrays of points instead of single points. I think it is almost okay, although you'd need to change the firstif, add anaxisparameter to thenp.linalg.normcalls and maybe a few things more (sort_triple, which I assume is another if your functions, might need to be adapted too). Btw, consider replacing everypow(x, 2)call withnp.square(x).a, b, cas arguments throughpwherepis an array of shape (3,3), and then unpackingpdoes not seem to work. Do you mean the shape of the input argument offhas to be of the same shape asA, at least hast three dimensions? Thanks for the hint withnp.square(x).ex = (b - a) / (np.linalg.norm(b - a))withex = (b - a) / (np.linalg.norm(b - a, axis=0)), etc. Each statement must work with all the points at the same time. There is no general way to automate it (efficiently, that is; you can use loops or comprehension for convenience, like in the answer, if performance is not a big issue).