mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-14 11:18:06 +08:00
71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
import numpy as np
|
|
|
|
__all__ = ['_safe_as_int']
|
|
|
|
|
|
def _safe_as_int(val, atol=1e-7):
|
|
"""
|
|
Attempt to safely cast values to integer format.
|
|
|
|
Parameters
|
|
----------
|
|
val : scalar or iterable of scalars
|
|
Number or container of numbers which are intended to be interpreted as
|
|
integers, e.g., for indexing purposes, but which may not carry integer
|
|
type.
|
|
atol : float
|
|
Absolute tolerance away from nearest integer to consider values in
|
|
``val`` functionally integers.
|
|
|
|
Returns
|
|
-------
|
|
val_int : NumPy scalar or ndarray of dtype `np.int64`
|
|
Returns the input value(s) coerced to dtype `np.int64` assuming all
|
|
were within ``atol`` of the nearest integer.
|
|
|
|
Notes
|
|
-----
|
|
This operation calculates ``val`` modulo 1, which returns the mantissa of
|
|
all values. Then all mantissas greater than 0.5 are subtracted from one.
|
|
Finally, the absolute tolerance from zero is calculated. If it is less
|
|
than ``atol`` for all value(s) in ``val``, they are rounded and returned
|
|
in an integer array. Or, if ``val`` was a scalar, a NumPy scalar type is
|
|
returned.
|
|
|
|
If any value(s) are outside the specified tolerance, an informative error
|
|
is raised.
|
|
|
|
Examples
|
|
--------
|
|
>>> _safe_as_int(7.0)
|
|
7
|
|
|
|
>>> _safe_as_int([9, 4, 2.9999999999])
|
|
array([9, 4, 3], dtype=int32)
|
|
|
|
>>> _safe_as_int(53.01)
|
|
Traceback (most recent call last):
|
|
...
|
|
ValueError: Integer argument required but received 53.1, check inputs.
|
|
|
|
>>> _safe_as_int(53.01, atol=0.01)
|
|
53
|
|
|
|
"""
|
|
mod = np.asarray(val) % 1 # Extract mantissa
|
|
|
|
# Check for and subtract any mod values > 0.5 from 1
|
|
if mod.ndim == 0: # Scalar input, cannot be indexed
|
|
if mod > 0.5:
|
|
mod = 1 - mod
|
|
else: # Iterable input, now ndarray
|
|
mod[mod > 0.5] = 1 - mod[mod > 0.5] # Test on each side of nearest int
|
|
|
|
try:
|
|
np.testing.assert_allclose(mod, 0, atol=atol)
|
|
except AssertionError:
|
|
raise ValueError("Integer argument required but received "
|
|
"{0}, check inputs.".format(val))
|
|
|
|
return np.round(val).astype(np.int64)
|