There is a procedure involving a search over an (eventually) big number of parameter combinations that I am trying to speed up using numba. I tried to change my initial code to make it compatible but still got a TypingError I do not know how to resolve. I had many issues when using 'np.asarray()' so I removed that and am mostly dealing with standard lists now but it still does not work. I will only mention the parts of the code that seem relevant given the error message, if more is needed, I will supply that too (just to keep it fairly short).
The seemingly crucial part of the error message (the rest, as far as I can tell, is just due to this function being called within another which is again called within another) reads:
Failed in nopython mode pipeline (step: nopython frontend) No implementation of function Function(<function dot at 0x0000021490EA2400>) found for signature:
dot(list(list(float64)<iv=None>)<iv=None>, reflected list(float64)<iv=None>)
There are 4 candidate implementations: - Of which 4 did not match due to: Overload in function '_OverloadWrapper._build..ol_generated': File: numba\core\overload_glue.py: Line 131. With argument(s): '(list(list(float64)<iv=None>)<iv=None>, reflected list(float64)<iv=None>)': Rejected as the implementation raised a specific error: TypingError: Failed in nopython mode pipeline (step: nopython frontend) No implementation of function Function() found for signature:
>>> stub(list(list(float64)<iv=None>)<iv=None>, reflected list(float64)<iv=None>)
It seems to originate from the function 'nvaxes_lab' defined as follows:
# reference position of NV axis vectors, each row holds the orientation (vector) of one NV axis
nvaxes_ref = [[1.0, 1.0, 1.0],
[-1.0, 1.0, -1.0], [1.0, -1.0, -1.0], [-1.0, -1.0, 1.0]]
@njit()
def rot_euler(a, b, g):
"""
:param a: float, angle of third rotation (around z-axis) in radians
:param b: float, angle of second rotation (around x-axis) in radians
:param g: float, angle of first rotation (around z-axis) in radians
:return: rotation matrix for a general rotation around the Euler angles a (=alpha), b (=beta), g (=gamma) defined
as follows: rot_euler(a,b,g) = rotZ(a).rotX(b).rotZ(g)
"""
return [[np.cos(a) * np.cos(g) - np.cos(b) * np.sin(a) * np.sin(g),
-np.cos(b) * np.cos(g) * np.sin(a) - np.cos(a) * np.sin(g), np.sin(a) * np.sin(b)],
[np.cos(g) * np.sin(a) np.cos(a) * np.cos(b) * np.sin(g),
np.cos(a) * np.cos(b) * np.cos(g) - np.sin(a) * np.sin(g), -np.cos(a) * np.sin(b)],
[np.sin(b) * np.sin(g), np.cos(g) * np.sin(b), np.cos(b)]]
@njit()
def nvaxes_lab(a, b, g):
"""
:param a: float, angle of third Euler rotation (around z-axis) in radians
:param b: float, angle of second Euler rotation (around x-axis) in radians
:param g: float, angle of first Euler rotation (around z-axis) in radians
:return: numpy array of dimensions 3x4, each row holds the orientation (vector) of the corresponding NV-axis
after rotation by the Euler angles a,b,g
"""
return [np.dot(rot_euler(a, b, g), nvaxes_ref[0]).astype(float), np.dot(rot_euler(a, b, g), nvaxes_ref[1]).astype(float),
np.dot(rot_euler(a, b, g).astype(float), nvaxes_ref[2]), np.dot(rot_euler(a, b, g), nvaxes_ref[3]).astype(float)]
The problem seems to be the dot product in each component of the array returned in 'nvaxes_lab' ... unfortunately, I have no idea how to define the arrays (I tried out multiple versions) or what else I could do to make this error disappear since this is the first time I am using numba.
I would appreciate your help!
CodePudding user response:
You have a couple of issues. First, the actual error you are seeing comes from when numba compile your function, it uses the C implementations of the numpy functions. Those implementations expect numpy arrays, not lists. So the error:
dot(list(list(float64)<iv=None>)<iv=None>, reflected list(float64)<iv=None>)
is basically trying to tell you that the np.dot
function doesn't know how to handle lists. In the python version, it will coerce the lists to a numpy array, but I guess not in the C/numba version. You can either wrap np.array
around each list, or a better option would be to output an array rot_euler
.
Next, it is best practice to not reference mutable variables that are defined outside the scope of the function that you are trying to JIT. In nvaxes_lab
, you reference each of the elements of nvaxes_ref
. You are better off passing those in as a parameter of the function, and to be consistent, also make them an array.
Last, you docstring doesn't match your return type for nvaxes_lab
. You can just vstack the entire list to make it an array.
In terms of converting stuff to floats, because the nvaxes_ref
array is already a float array, all of the outputs will be floats as well, so you can drop the astype
methods.
import numpy as np
from numba import njit
nvaxes_ref = np.array([
[1.0, 1.0, 1.0],
[-1.0, 1.0, -1.0],
[1.0, -1.0, -1.0],
[-1.0, -1.0, 1.0]
])
@njit
def rot_euler(a, b, g):
"""
:param a: float, angle of third rotation (around z-axis) in radians
:param b: float, angle of second rotation (around x-axis) in radians
:param g: float, angle of first rotation (around z-axis) in radians
:return: rotation matrix for a general rotation around the Euler angles
a (=alpha), b (=beta), g (=gamma) defined as follows:
rot_euler(a,b,g) = rotZ(a).rotX(b).rotZ(g)
"""
return np.array([
[
np.cos(a) * np.cos(g) - np.cos(b) * np.sin(a) * np.sin(g),
-np.cos(b) * np.cos(g) * np.sin(a) - np.cos(a) * np.sin(g),
np.sin(a) * np.sin(b)
],
[
np.cos(g) * np.sin(a) np.cos(a) * np.cos(b) * np.sin(g),
np.cos(a) * np.cos(b) * np.cos(g) - np.sin(a) * np.sin(g),
-np.cos(a) * np.sin(b)
],
[
np.sin(b) * np.sin(g),
np.cos(g) * np.sin(b),
np.cos(b)
]
])
@njit
def nvaxes_lab(a, b, g, refs):
"""
:param a: float, angle of third Euler rotation (around z-axis) in radians
:param b: float, angle of second Euler rotation (around x-axis) in radians
:param g: float, angle of first Euler rotation (around z-axis) in radians
:return: numpy array of dimensions 3x4, each row holds the orientation (vector)
of the corresponding NV-axis after rotation by the Euler angles a,b,g
"""
return [
np.dot(rot_euler(a, b, g), refs[0]),
np.dot(rot_euler(a, b, g), refs[1]),
np.dot(rot_euler(a, b, g), refs[2]),
np.dot(rot_euler(a, b, g), refs[3])
]