Using builtin round() in numba

I am trying to use round() in my function (fps is 14 as integer):

@jit(nopython=True)
def freezing_time(
    fps: Union[float, int],
    *displacements: Iterable[np.ndarray],
    second_threshold: float = 1.0,
    metric_displacement_threshold: float = 0.005,
):
    frame_threshold = round(second_threshold * fps)

Numba is complaining about the round function not being supported in the way I am using. Not sure what is wrong here, any help is appreciated.

Here is the error log:

Traceback (most recent call last):
  File "/home/can/PycharmProjects/BiKiPy/examples/nort_belhaj_analysis/nort_analysis.py", line 92, in <module>
    NortExperiment(
  File "/home/can/PycharmProjects/BiKiPy/bikipy/behaviour/nort/experiment.py", line 139, in __init__
    exp := NortHabituationTrial(
  File "/home/can/PycharmProjects/BiKiPy/bikipy/behaviour/nort/trial.py", line 145, in __init__
    self.freezing_time
  File "/home/can/.pyenv/versions/3.9.4/lib/python3.9/functools.py", line 969, in __get__
    val = self.func(instance)
  File "/home/can/PycharmProjects/BiKiPy/bikipy/behaviour/nort/trial.py", line 149, in freezing_time
    return freezing_time(
  File "/home/can/.cache/pypoetry/virtualenvs/bikipy-V2iGsb6g-py3.9/lib/python3.9/site-packages/numba/core/dispatcher.py", line 420, in _compile_for_args
    error_rewrite(e, 'typing')
  File "/home/can/.cache/pypoetry/virtualenvs/bikipy-V2iGsb6g-py3.9/lib/python3.9/site-packages/numba/core/dispatcher.py", line 361, in error_rewrite
    raise e.with_traceback(None)
numba.core.errors.TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function round>) found for signature:
 
 >>> round(array(float64, 1d, C))
 
There are 2 candidate implementations:
   - Of which 2 did not match due to:
   Type Restricted Function in function 'round': File: unknown: Line unknown.
     With argument(s): '(array(float64, 1d, C))':
    No match for registered cases:
     * (float32,) -> int64
     * (float64,) -> int64
     * (float32, int64) -> float32
     * (float64, int64) -> float64

During: resolving callee type: Function(<built-in function round>)
During: typing of call at /home/can/PycharmProjects/BiKiPy/bikipy/feature/motion.py (149)


File "../../bikipy/feature/motion.py", line 149:
def freezing_time(
    <source elided>
    """
    frame_threshold = round(second_threshold * fps)
    ^

Hi @caniko

How are you calling that function? The signature suggests that second_threshold and fps are scalars. But the error message looks to me as if at least one of them was passed as a numpy array. If that is indeed the case you need to use numpy’s round function, if not something might be fishy.

Does this function run without the jit-decorator?

freezing_time(
    self.fps,
    *tuple(np.ndarray, ...),
)

I always thought that whatever is inside the tuple fell under displacements, but you are that is not the case, or?

mhm, maybe what I wrote was not fully clear: I agree with you that everything in *tuple(....) should go into *displacements. But that is not the problem here, as far as I can tell.

Are you sure that self.fps is a scalar? Or is it something funny like a numpy array with a single entry? round is a python builtin and does not work with numpy arrays (even without numba). That is why I asked if your code runs when you remove the numba decorator, or if that also fails (then it is clearly not numba’s fault)

If self.fps is a plain python float variable, then there is a problem indeed.

To illustrate my point:

In [1]: import numpy

In [2]: from numba import njit

In [3]: @njit
   ...: def fun(fps):
   ...:     return round(fps)
   ...: 

In [4]: fun(14.5)  # This runs as expected
Out[4]: 14

In [5]: fun(numpy.array([1.5]))  # This throws the same error as in your initial post
---------------------------------------------------------------------------
TypingError                               Traceback (most recent call last)
<ipython-input-5-ae319fb423de> in <module>
----> 1 fun(numpy.array([1.5]))

~/anaconda3/envs/py38/lib/python3.8/site-packages/numba/core/dispatcher.py in _compile_for_args(self, *args, **kws)
    418                 e.patch_message(msg)
    419 
--> 420             error_rewrite(e, 'typing')
    421         except errors.UnsupportedError as e:
    422             # Something unsupported is present in the user code, add help info

~/anaconda3/envs/py38/lib/python3.8/site-packages/numba/core/dispatcher.py in error_rewrite(e, issue_type)
    359                 raise e
    360             else:
--> 361                 raise e.with_traceback(None)
    362 
    363         argtypes = []

TypingError: Failed in nopython mode pipeline (step: nopython frontend)
No implementation of function Function(<built-in function round>) found for signature:
 
 >>> round(array(float64, 1d, C))
 
There are 2 candidate implementations:
  - Of which 2 did not match due to:
  Type Restricted Function in function 'round': File: unknown: Line unknown.
    With argument(s): '(array(float64, 1d, C))':
   No match for registered cases:
    * (float32,) -> int64
    * (float64,) -> int64
    * (float32, int64) -> float32
    * (float64, int64) -> float64

During: resolving callee type: Function(<built-in function round>)
During: typing of call at <ipython-input-3-66bd25b7c3c2> (3)


File "<ipython-input-3-66bd25b7c3c2>", line 3:
def fun(fps):
    return round(fps)
    ^