diff --git a/lib/galaxy/tool_util/verify/asserts/image.py b/lib/galaxy/tool_util/verify/asserts/image.py index 76ff0425da9..622758395e9 100644 --- a/lib/galaxy/tool_util/verify/asserts/image.py +++ b/lib/galaxy/tool_util/verify/asserts/image.py @@ -2,7 +2,8 @@ import io from typing import ( Optional, Union, - List + List, + Tuple, ) import numpy @@ -32,6 +33,53 @@ def assert_image_has_metadata( f"Image has wrong number of channels: {actual_channels} (expected {int(channels)})" +def _compute_center_of_mass(im_arr): + while im_arr.ndim > 2: + im_arr = im_arr.sum(axis=2) + im_arr = numpy.abs(im_arr) + if im_arr.sum() == 0: + return (numpy.nan, numpy.nan) + im_arr = im_arr / im_arr.sum() + yy, xx = numpy.indices(im_arr.shape) + return (im_arr * xx).sum(), (im_arr * yy).sum() + + +def assert_image_has_intensities( + output_bytes: bytes, + channel: Optional[Union[int, str]] = None, + mean_intensity: Optional[Union[float, str]] = None, + center_of_mass: Optional[Union[Tuple[float], str]] = None, + eps: Optional[Union[float, str]] = 1e-8, +) -> None: + """ + Assert the image output has specific intensity content. + """ + buf = io.BytesIO(output_bytes) + with Image.open(buf) as im: + im_arr = numpy.array(im) + + # Select the specified channel (if any). + if channel is not None: + im_arr = im_arr[:, :, channel] + + # Perform `mean_intensity` assertion. + if mean_intensity is not None: + actual = im_arr.mean() + expected = float(mean_intensity) + assert abs(actual - expected) <= float(eps), \ + f"Wrong mean intensity: {actual} (expected {expected})" + + # Perform `center_of_mass` assertion. + if center_of_mass is not None: + if isinstance(center_of_mass, str): + center_of_mass = [float(c.strip()) for c in center_of_mass.split(",")] + assert len(center_of_mass) == 2, "center_of_mass must have two components" + actual = _compute_center_of_mass(im_arr) + distance = numpy.linalg.norm(numpy.subtract(center_of_mass, expected)) + assert distance <= float(eps), \ + f"Wrong center of mass: {actual} (expected {center_of_mass})" + + def assert_image_has_labels( output_bytes: bytes, number_of_objects: Optional[Union[int, str]] = None, diff --git a/test/functional/tools/validation_image.xml b/test/functional/tools/validation_image.xml index 23cc130136b..7a0c561426a 100644 --- a/test/functional/tools/validation_image.xml +++ b/test/functional/tools/validation_image.xml @@ -14,7 +14,7 @@ - + @@ -23,6 +23,25 @@ + + + + + + + + + + + + + + + + + + +