bcaae5ec22
Rename the distribution to image-filter and imports to image_filter. Keep medical fixtures local and document their setup for fresh clones. Include composite pipelines, consistent examples, and class diagrams.
52 lines
2.3 KiB
Python
52 lines
2.3 KiB
Python
"""Composite behavior: substitution, ordering, metadata, and adapters."""
|
|
import json
|
|
|
|
import numpy as np
|
|
import pytest
|
|
|
|
from image_filter import (
|
|
CannyFilter, GaussianFilter, ImageFilter, ImageItem, InvalidConfigurationError,
|
|
MeanFilter, Pipeline, SliceWise, SobelFilter, UnsupportedDimensionError,
|
|
)
|
|
|
|
|
|
def test_nested_pipeline_matches_explicit_execution_and_preserves_metadata():
|
|
image = np.arange(120, dtype=float).reshape(10, 12)
|
|
metadata = {"patient": {"label": "test"}}
|
|
first, second, third = MeanFilter(3), GaussianFilter(0.8), SobelFilter()
|
|
operation = Pipeline([Pipeline([first, second]), third])
|
|
assert isinstance(operation, ImageFilter)
|
|
result = operation.apply(image, metadata)
|
|
expected = third.apply(second.apply(first.apply(image).image).image)
|
|
np.testing.assert_array_equal(result.image, expected.image)
|
|
assert [x["filter"] for x in result.metadata["processing_history"]] == [
|
|
"MeanFilter", "GaussianFilter", "SobelFilter",
|
|
]
|
|
assert metadata == {"patient": {"label": "test"}}
|
|
assert result.metadata["patient"] is not metadata["patient"]
|
|
np.testing.assert_array_equal(image, np.arange(120).reshape(10, 12))
|
|
for component in (first, operation):
|
|
batch = component.apply_batch([ImageItem(image), ImageItem(image[None])])
|
|
np.testing.assert_array_equal(batch[0].image, batch[1].image[0])
|
|
|
|
|
|
def test_pipeline_in_slicewise_preserves_boolean_output_and_serializable_history():
|
|
volume = np.random.default_rng(12).random((10, 12, 5))
|
|
pipeline = Pipeline([GaussianFilter(0.8), CannyFilter(use_quantiles=True)])
|
|
result = SliceWise(pipeline, axis=2).apply(volume)
|
|
expected = np.stack([pipeline.apply(volume[:, :, i]).image for i in range(5)], axis=2)
|
|
np.testing.assert_array_equal(result.image, expected)
|
|
assert result.image.dtype == bool
|
|
json.dumps(dict(result.metadata))
|
|
assert pipeline.capabilities.spatial_dimensions == frozenset({2})
|
|
with pytest.raises(UnsupportedDimensionError):
|
|
pipeline.apply(volume)
|
|
|
|
|
|
def test_invalid_composites_fail_at_construction():
|
|
for steps in ([], [object()], [Pipeline([MeanFilter()]), "invalid"]):
|
|
with pytest.raises(InvalidConfigurationError):
|
|
Pipeline(steps)
|
|
with pytest.raises(InvalidConfigurationError):
|
|
SliceWise(object(), axis=0)
|