68 lines
2.3 KiB
Python
68 lines
2.3 KiB
Python
import numpy as np
|
|
import pytest
|
|
from tests.node_tests._shared import make_field
|
|
|
|
|
|
def test_local_contrast_shape_preserved():
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
node = LocalContrast()
|
|
field = make_field(shape=(48, 64))
|
|
result, = node.process(field, kernel_size=10, weight=0.5)
|
|
assert result.data.shape == (48, 64)
|
|
|
|
|
|
def test_local_contrast_weight_zero_unchanged():
|
|
"""weight=0 blends 100% original → result equals input."""
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
node = LocalContrast()
|
|
data = np.random.default_rng(0).standard_normal((32, 32))
|
|
field = make_field(data=data)
|
|
result, = node.process(field, kernel_size=5, weight=0.0)
|
|
assert np.allclose(result.data, data)
|
|
|
|
|
|
def test_local_contrast_uniform_field_unchanged():
|
|
"""A flat field has nothing to enhance; it should be returned as-is."""
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
node = LocalContrast()
|
|
field = make_field(data=np.full((32, 32), 2.0))
|
|
result, = node.process(field, kernel_size=5, weight=1.0)
|
|
assert np.allclose(result.data, 2.0)
|
|
|
|
|
|
def test_local_contrast_increases_dynamic_range():
|
|
"""Weight=1 full enhancement should not compress global range beyond input."""
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
rng = np.random.default_rng(1)
|
|
data = rng.standard_normal((64, 64))
|
|
field = make_field(data=data)
|
|
node = LocalContrast()
|
|
result, = node.process(field, kernel_size=8, weight=1.0)
|
|
# Global min/max should be preserved (by construction of the algorithm)
|
|
assert np.isclose(result.data.min(), data.min(), atol=1e-6)
|
|
assert np.isclose(result.data.max(), data.max(), atol=1e-6)
|
|
|
|
|
|
def test_local_contrast_preserves_metadata():
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
node = LocalContrast()
|
|
field = make_field()
|
|
result, = node.process(field, kernel_size=10, weight=0.5)
|
|
assert result.xreal == field.xreal
|
|
assert result.si_unit_z == field.si_unit_z
|
|
|
|
|
|
def test_local_contrast_weight_clipped():
|
|
"""Values outside [0,1] should be clipped without error."""
|
|
from backend.nodes.local_contrast import LocalContrast
|
|
|
|
node = LocalContrast()
|
|
field = make_field()
|
|
result, = node.process(field, kernel_size=5, weight=2.0)
|
|
assert result.data.shape == field.data.shape
|