diff --git a/movement/utils/vector.py b/movement/utils/vector.py index ca7430df1..ec6d92758 100644 --- a/movement/utils/vector.py +++ b/movement/utils/vector.py @@ -82,7 +82,10 @@ def convert_to_unit(data: xr.DataArray) -> xr.DataArray: """ if "space" in data.dims: validate_dims_coords(data, {"space": ["x", "y"]}) - return data / compute_norm(data) + norm = compute_norm(data) + unit = data / norm + unit = xr.where(norm == 0, np.nan, unit) + return unit elif "space_pol" in data.dims: validate_dims_coords(data, {"space_pol": ["rho", "phi"]}) # Set both rho and phi values to NaN at null vectors (where rho = 0) @@ -144,8 +147,7 @@ def cart2pol(data: xr.DataArray) -> xr.DataArray: # Make all zeros in phi positive zeros # - where rho == 0, set phi to 0 # - where rho != 0, keep the phi value from atan2 - phi = xr.where(np.isclose(rho.values, 0.0, atol=1e-9), 0.0, phi) - + phi = xr.where(np.isclose(rho, 0.0, atol=1e-9), 0.0, phi) # Replace space dim with space_pol dims = list(data.dims) dims[dims.index("space")] = "space_pol" @@ -298,11 +300,12 @@ def compute_signed_angle_2d( cross *= -1.0 dot = u_x * v_x + u_y * v_y - angles = np.arctan2(cross, dot) - assert isinstance(angles, xr.DataArray) + angles = xr.apply_ufunc(np.arctan2, cross, dot) + # arctan2 returns values in [-pi, pi]. - # We need to map -pi angles to pi, to stay in the (-pi, pi] range - angles.values[angles <= -np.pi] = np.pi + # Map -pi to pi to stay in the (-pi, pi] range + angles = xr.where(angles <= -np.pi, np.pi, angles) + angles.name = "signed_angle" return angles diff --git a/pyproject.toml b/pyproject.toml index c8cb184bd..3ce349f28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ dependencies = [ "numpy>=2.0.0", "pandas", "h5py", - "netCDF4<1.7.3", + "netCDF4>=1.7.2,<1.7.3", "tables>=3.10.1", "attrs", "pooch",