import numpy as np import pytest import sys import os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from slic.utils.npy import * @pytest.mark.parametrize("start, stop, step, expected", [ (0, 5, 1, np.linspace(0, 5, 6)), # regular integer step (5, 0, -1, np.linspace(5, 0, 6)), # reversed with negative step (1, 2, 0.3, np.linspace(1, 2, 4)), # step doesn't divide evenly (-2, 2, 1.5, np.linspace(-2, 2, 3)), # centered range (2.5, 0.5, -0.4, np.linspace(2.5, 0.5, 6)), # reversed float ]) def test_nice_arange(start, stop, step, expected): np.testing.assert_allclose(nice_arange(start, stop, step), expected, rtol=1e-6) @pytest.mark.parametrize("start, stop, num, expected", [ (0, 10, 4, np.array([0., 2.5, 5., 7.5, 10.])), # basic (5, 15, 2, np.array([5., 10., 15.])), # evenly spaced 3 points (-5, 5, 4, np.array([-5., -2.5, 0., 2.5, 5.])), # negative to positive (0, 1, 3, np.array([0., 1/3, 2/3, 1.])), # fractions (non-integers) (2, 2, 3, np.array([2., 2., 2., 2.])), # constant start = stop (3, 0, 3, np.array([3., 2., 1., 0.])), # decreasing (0, 1, 0, np.array([0.])), # edge case: 0 intervals → 1 point ]) def test_nice_linspace(start, stop, num, expected): np.testing.assert_allclose(nice_linspace(start, stop, num), expected) @pytest.mark.parametrize("start, stop, step, endpoint, expected", [ (-2, 2, 2, True, np.array([-2., 0., 2.])), # symmetric around 0 (0, 5, 2, True, np.array([0., 2., 4.])), # basic (0, 5, 2, False, np.array([0., 2.])), # no endpoint (-1, 2, 1.5, True, np.array([-1.5, 0., 1.5])) # step doesn't fit exactly ]) def test_nice_steps_centered(start, stop, step, endpoint, expected): np.testing.assert_allclose(nice_steps_centered(start, stop, step, endpoint), expected) @pytest.mark.parametrize("start, stop, step, endpoint, expected", [ (0, 5, 2, True, np.array([0., 2., 4., 6.])), # Normal case with endpoint overshooting (0, 5, 2, False, np.array([0., 2., 4.])), # No endpoint (-1, 2, 1.5, True, np.array([-1., 0.5, 2.])), # Needs fractional alignment to include stop (-1, 2, 1.5, False, np.array([-1., 0.5])), # Same range but no endpoint (-2, 1, 1.2, True, np.array([-2., -0.8, 0.4, 1.6])), # Step overshoots (5, 0, -2, True, np.array([5., 3., 1., -1.])), # Backward steps with overshoot (5, 0, -2, False, np.array([5., 3., 1.])), # No endpoint, backward ]) def test_nice_steps_left_aligned(start, stop, step, endpoint, expected): np.testing.assert_allclose(nice_steps_left_aligned(start, stop, step, endpoint), expected) @pytest.mark.parametrize("start, stop, step, endpoint, expected", [ (0, 5, 2, True, np.array([6., 4., 2., 0.])), # Right-aligned, overshoots left (0, 5, 2, False, np.array([4., 2., 0.])), # Right-aligned, no endpoint (-1, 2, 1.5, True, np.array([2., 0.5, -1.])), # Step doesn t divide evenly, reverse it (-1, 2, 1.5, False, np.array([0.5, -1.])), # Without endpoint (5, 0, -2, True, np.array([5., 3., 1., -1.])), # Negative step, includes endpoint overshoot (5, 0, -2, False, np.array([3., 1., -1.])), # No endpoint, skips last one (-3, 3, 2, True, np.array([5., 3., 1., -1., -3.])), # Large symmetric range, reverse ]) def test_nice_steps_right_aligned(start, stop, step, endpoint, expected): np.testing.assert_allclose(nice_steps_right_aligned(start, stop, step, endpoint), expected) @pytest.mark.parametrize("val, vmin, vmax, expected", [ (5, 0, 10, True), (5, 6, 10, False), (5, None, 10, True), (5, 0, None, True), (5, None, None, True), ]) def test_within_scalar(val, vmin, vmax, expected): assert within(val, vmin, vmax) == expected @pytest.mark.parametrize("data, vmin, vmax, expected", [ ([1, 2, 3, 4, 5], 2, 5, 0.6), ([10, 20, 30], 5, 25, 2/3), ([1, 2, 3], None, 2, 1/3), ([], 0, 1, 0), ]) def test_within_fraction(data, vmin, vmax, expected): result = within_fraction(data, vmin, vmax) assert np.isclose(result, expected) @pytest.mark.parametrize("fraction, ndigits, expected", [ (0.456, 1, 45.6), (0.12345, 2, 12.35), (0.9999, 0, 100.0), ]) def test_fraction_to_percentage(fraction, ndigits, expected): assert fraction_to_percentage(fraction, ndigits) == expected @pytest.mark.parametrize("val, expected", [ (np.array([1, 2, 3]), np.ndarray), ([1, 2, 3], list), (3.14, float), ]) def test_get_dtype(val, expected): dtype = get_dtype(val) if isinstance(dtype, type): assert dtype == expected else: assert isinstance(dtype, np.dtype) @pytest.mark.parametrize("val, expected", [ (np.array([[1, 2], [3, 4]]), (2, 2)), ([1, 2, 3], ()), (42, ()), ]) def test_get_shape(val, expected): assert get_shape(val) == expected @pytest.mark.parametrize("val, expected", [ (np.array([1, 2, 3]), True), ([1, 2, 3], False), (42, False), ]) def test_is_array(val, expected): assert is_array(val) == expected