Merge pull request #17581 from kostrykin/files_assertions_images

Add content assertion XML tags for test output verification using images
This commit is contained in:
Marius van den Beek
2024-03-13 13:08:55 +01:00
committed by GitHub
5 changed files with 747 additions and 1 deletions
@@ -11,7 +11,7 @@ from galaxy.util.compression_utils import get_fileobj
log = logging.getLogger(__name__)
assertion_module_names = ["text", "tabular", "xml", "json", "hdf5", "archive", "size"]
assertion_module_names = ["text", "tabular", "xml", "json", "hdf5", "archive", "size", "image"]
# Code for loading modules containing assertion checking functions, to
# create a new module of assertion functions, create the needed python
@@ -0,0 +1,289 @@
import io
from typing import (
Any,
List,
Optional,
Tuple,
TYPE_CHECKING,
Union,
)
from ._util import _assert_number
try:
import numpy
except ImportError:
pass
try:
from PIL import Image
except ImportError:
pass
if TYPE_CHECKING:
import numpy.typing
def _assert_float(
actual: float,
label: str,
tolerance: Union[float, str],
expected: Optional[Union[float, str]] = None,
range_min: Optional[Union[float, str]] = None,
range_max: Optional[Union[float, str]] = None,
) -> None:
# Perform `tolerance` based check.
if expected is not None:
assert abs(actual - float(expected)) <= float(
tolerance
), f"Wrong {label}: {actual} (expected {expected} ±{tolerance})"
# Perform `range_min` based check.
if range_min is not None:
assert actual >= float(range_min), f"Wrong {label}: {actual} (must be {range_min} or larger)"
# Perform `range_max` based check.
if range_max is not None:
assert actual <= float(range_max), f"Wrong {label}: {actual} (must be {range_max} or smaller)"
def assert_has_image_width(
output_bytes: bytes,
width: Optional[Union[int, str]] = None,
delta: Union[int, str] = 0,
min: Optional[Union[int, str]] = None,
max: Optional[Union[int, str]] = None,
negate: Union[bool, str] = False,
) -> None:
"""
Asserts the specified output is an image and has a width of the specified value.
"""
buf = io.BytesIO(output_bytes)
with Image.open(buf) as im:
_assert_number(
im.size[0],
width,
delta,
min,
max,
negate,
"{expected} width {n}+-{delta}",
"{expected} width to be in [{min}:{max}]",
)
def assert_has_image_height(
output_bytes: bytes,
height: Optional[Union[int, str]] = None,
delta: Union[int, str] = 0,
min: Optional[Union[int, str]] = None,
max: Optional[Union[int, str]] = None,
negate: Union[bool, str] = False,
) -> None:
"""
Asserts the specified output is an image and has a height of the specified value.
"""
buf = io.BytesIO(output_bytes)
with Image.open(buf) as im:
_assert_number(
im.size[1],
height,
delta,
min,
max,
negate,
"{expected} height {n}+-{delta}",
"{expected} height to be in [{min}:{max}]",
)
def assert_has_image_channels(
output_bytes: bytes,
channels: Optional[Union[int, str]] = None,
delta: Union[int, str] = 0,
min: Optional[Union[int, str]] = None,
max: Optional[Union[int, str]] = None,
negate: Union[bool, str] = False,
) -> None:
"""
Asserts the specified output is an image and has the specified number of channels.
"""
buf = io.BytesIO(output_bytes)
with Image.open(buf) as im:
_assert_number(
len(im.getbands()),
channels,
delta,
min,
max,
negate,
"{expected} image channels {n}+-{delta}",
"{expected} image channels to be in [{min}:{max}]",
)
def _compute_center_of_mass(im_arr: "numpy.typing.NDArray") -> Tuple[float, float]:
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 _get_image(
output_bytes: bytes,
channel: Optional[Union[int, str]] = None,
) -> "numpy.typing.NDArray":
"""
Returns the output image or a specific channel.
"""
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[:, :, int(channel)]
# Return the image
return im_arr
def assert_has_image_mean_intensity(
output_bytes: bytes,
channel: Optional[Union[int, str]] = None,
mean_intensity: Optional[Union[float, str]] = None,
eps: Union[float, str] = 0.01,
min: Optional[Union[float, str]] = None,
max: Optional[Union[float, str]] = None,
) -> None:
"""
Asserts the specified output is an image and has the specified mean intensity value.
"""
im_arr = _get_image(output_bytes, channel)
_assert_float(
actual=im_arr.mean(),
label="mean intensity",
tolerance=eps,
expected=mean_intensity,
range_min=min,
range_max=max,
)
def assert_has_image_center_of_mass(
output_bytes: bytes,
center_of_mass: Union[Tuple[float, float], str],
channel: Optional[Union[int, str]] = None,
eps: Union[float, str] = 0.01,
) -> None:
"""
Asserts the specified output is an image and has the specified center of mass.
"""
im_arr = _get_image(output_bytes, channel)
if isinstance(center_of_mass, str):
center_of_mass_parts = [c.strip() for c in center_of_mass.split(",")]
assert len(center_of_mass_parts) == 2
center_of_mass = (float(center_of_mass_parts[0]), float(center_of_mass_parts[1]))
assert len(center_of_mass) == 2, "center_of_mass must have two components"
actual_center_of_mass = _compute_center_of_mass(im_arr)
distance = numpy.linalg.norm(numpy.subtract(center_of_mass, actual_center_of_mass))
assert distance <= float(
eps
), f"Wrong center of mass: {actual_center_of_mass} (expected {center_of_mass}, distance: {distance}, eps: {eps})"
def _get_image_labels(
output_bytes: bytes,
channel: Optional[Union[int, str]] = None,
labels: Optional[Union[str, List[int]]] = None,
exclude_labels: Optional[Union[str, List[int]]] = None,
) -> Tuple["numpy.typing.NDArray", List[Any]]:
"""
Determines the unique labels in the output image or a specific channel.
"""
assert labels is None or exclude_labels is None
im_arr = _get_image(output_bytes, channel)
def cast_label(label):
label = label.strip()
if numpy.issubdtype(im_arr.dtype, numpy.integer):
return int(label)
if numpy.issubdtype(im_arr.dtype, float):
return float(label)
raise AssertionError(f'Unsupported image label type: "{im_arr.dtype}"')
# Determine labels present in the image.
present_labels = numpy.unique(im_arr)
# Apply filtering due to `labels` (keep only those).
if labels is None:
labels = []
if isinstance(labels, str):
labels = [cast_label(label) for label in labels.split(",") if len(label) > 0]
if len(labels) > 0:
present_labels = [label for label in present_labels if label in labels]
# Apply filtering due to `exclude_labels`.
if exclude_labels is None:
exclude_labels = []
if isinstance(exclude_labels, str):
exclude_labels = [cast_label(label) for label in exclude_labels.split(",") if len(label) > 0]
present_labels = [label for label in present_labels if label not in exclude_labels]
# Return the image data and the labels.
return im_arr, present_labels
def assert_has_image_n_labels(
output_bytes: bytes,
channel: Optional[Union[int, str]] = None,
exclude_labels: Optional[Union[str, List[int]]] = None,
n: Optional[Union[int, str]] = None,
delta: Union[int, str] = 0,
min: Optional[Union[int, str]] = None,
max: Optional[Union[int, str]] = None,
negate: Union[bool, str] = False,
) -> None:
"""
Asserts the specified output is an image and has the specified number of unique values (e.g., uniquely labeled objects).
"""
present_labels = _get_image_labels(output_bytes, channel, exclude_labels)[1]
_assert_number(
len(present_labels),
n,
delta,
min,
max,
negate,
"{expected} labels {n}+-{delta}",
"{expected} labels to be in [{min}:{max}]",
)
def assert_has_image_mean_object_size(
output_bytes: bytes,
channel: Optional[Union[int, str]] = None,
labels: Optional[Union[str, List[int]]] = None,
exclude_labels: Optional[Union[str, List[int]]] = None,
mean_object_size: Optional[Union[float, str]] = None,
eps: Union[float, str] = 0.01,
min: Optional[Union[float, str]] = None,
max: Optional[Union[float, str]] = None,
) -> None:
"""
Asserts the specified output is an image with labeled objects which have the specified mean size (number of pixels).
"""
im_arr, present_labels = _get_image_labels(output_bytes, channel, labels, exclude_labels)
actual_mean_object_size = sum((im_arr == label).sum() for label in present_labels) / len(present_labels)
_assert_float(
actual=actual_mean_object_size,
label="mean object size",
tolerance=eps,
expected=mean_object_size,
range_min=min,
range_max=max,
)
+274
View File
@@ -2178,6 +2178,7 @@ module.
<xs:group ref="TestAssertionsXml" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsJson" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsH5" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsImage" minOccurs="0" maxOccurs="unbounded"/>
</xs:choice>
</xs:complexType>
<xs:group name="TestAssertionsGeneral">
@@ -2242,6 +2243,20 @@ module.
<xs:element name="has_json_property_with_text" type="AssertHasJsonPropertyWithText"/>
</xs:choice>
</xs:group>
<xs:group name="TestAssertionsImage">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[Assertions for image data]]></xs:documentation>
</xs:annotation>
<xs:choice>
<xs:element name="has_image_width" type="AssertHasImageWidth" />
<xs:element name="has_image_height" type="AssertHasImageHeight" />
<xs:element name="has_image_channels" type="AssertHasImageChannels" />
<xs:element name="has_image_mean_intensity" type="AssertHasImageMeanIntensity" />
<xs:element name="has_image_center_of_mass" type="AssertHasImageCenterOfMass" />
<xs:element name="has_image_n_labels" type="AssertHasImageNLabels" />
<xs:element name="has_image_mean_object_size" type="AssertHasImageMeanObjectSize" />
</xs:choice>
</xs:group>
<xs:group name="TestAssertionsH5">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[Assertions for H5 data]]></xs:documentation>
@@ -2490,6 +2505,7 @@ $attribute_list::5
<xs:group ref="TestAssertionsJson" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsXml" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsH5" minOccurs="0" maxOccurs="unbounded"/>
<xs:group ref="TestAssertionsImage" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="path" type="xs:string">
<xs:annotation>
@@ -2739,6 +2755,264 @@ $attribute_list::5
<xs:attributeGroup ref="AssertAttributePath"/>
<xs:attributeGroup ref="AssertAttributeNegate"/>
</xs:complexType>
<xs:complexType name="AssertHasImageWidth">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has a specific width (in pixels),
plus/minus ``delta`` (e.g., ``<has_image_width width="512" delta="2" />``).
Alternatively the range of the expected width can be specified by ``min`` and/or ``max``.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="width" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Expected width of the image (in pixels).`</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="delta" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed difference of the image width (in pixels, default is 0). The observed width has to be in the range ``value +- delta``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Minimum allowed width of the image (in pixels).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed width of the image (in pixels).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup ref="AssertAttributeNegate"/>
</xs:complexType>
<xs:complexType name="AssertHasImageHeight">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has a specific height (in pixels),
plus/minus ``delta`` (e.g., ``<has_image_height height="512" delta="2" />``).
Alternatively the range of the expected height can be specified by ``min`` and/or ``max``.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="height" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Expected height of the image (in pixels).`</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="delta" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed difference of the image height (in pixels, default is 0). The observed height has to be in the range ``value +- delta``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Minimum allowed height of the image (in pixels).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed height of the image (in pixels).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup ref="AssertAttributeNegate"/>
</xs:complexType>
<xs:complexType name="AssertHasImageChannels">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has a specific number of channels,
plus/minus ``delta`` (e.g., ``<has_image_channels channels="3" />``).
Alternatively the range of the expected number of channels can be specified by ``min`` and/or ``max``.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="channels" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Expected number of channels of the image.`</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="delta" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed difference of the number of channels (default is 0). The observed number of channels has to be in the range ``value +- delta``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Minimum allowed number of channels.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed number of channels.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup ref="AssertAttributeNegate"/>
</xs:complexType>
<xs:complexType name="AssertHasImageMeanIntensity">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has a specific mean intensity value,
plus/minus ``eps`` (e.g., ``<image_has_mean_intensity mean_intensity="0.83" />``).
Alternatively the range of the expected mean intensity value can be specified by ``min`` and/or ``max``.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="mean_intensity" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The required mean value of the image intensities.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eps" type="xs:float" use="optional" default="0.01">
<xs:annotation>
<xs:documentation xml:lang="en">The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean value of the image intensities has to be in the range ``value +- eps``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">A lower bound of the required mean value of the image intensities.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">An upper bound of the required mean value of the image intensities.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="channel" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="AssertHasImageCenterOfMass">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has a specific center of mass,
or has an Euclidean distance of ``eps`` or less to that point (e.g.,
``<has_image_center_of_mass center_of_mass="511.07, 223.34" />``).
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="center_of_mass" type="xs:string">
<xs:annotation>
<xs:documentation xml:lang="en">The required center of mass of the image intensities (horizontal and vertical coordinate, separated by a comma).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eps" type="xs:float" use="optional" default="0.01">
<xs:annotation>
<xs:documentation xml:lang="en">The maximum allowed Euclidean distance to the required center of mass (defaults to ``0.01``).</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="channel" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel).</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="AssertHasImageNLabels">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image and has the specified number of labels, or unique values (e.g.,
``<has_image_n_labels n="187" exclude_labels="0" />``).
The primary usage of this assertion is to verify the number of objects in images with uniquely labeled objects.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="n" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Expected number of labels.`</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="delta" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed difference of the number of labels (default is 0). The observed number of labels has to be in the range ``value +- delta``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Minimum allowed number of labels.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Maximum allowed number of labels.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="channel" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel). Must be used with multi-channel imags.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="labels" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="exclude_labels" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup ref="AssertAttributeNegate"/>
</xs:complexType>
<xs:complexType name="AssertHasImageMeanObjectSize">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
Asserts the output is an image with labeled objects which have the specified mean size (number of pixels),
plus/minus ``eps`` (e.g., ``<has_image_mean_object_size mean_object_size="111.87" exclude_labels="0" />``).
The labels must be unique.
$attribute_list::5
]]>
</xs:documentation>
</xs:annotation>
<xs:attribute name="mean_object_size" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">The required mean size of the uniquely labeled objects.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="eps" type="xs:float" use="optional" default="0.01">
<xs:annotation>
<xs:documentation xml:lang="en">The absolute tolerance to be used for ``value`` (defaults to ``0.01``). The observed mean size of the uniquely labeled objects has to be in the range ``value +- eps``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="min" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">A lower bound of the required mean size of the uniquely labeled objects.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="max" type="xs:float" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">An upper bound of the required mean size of the uniquely labeled objects.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="channel" type="xs:integer" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">Restricts the assertion to a specific channel of the image (where ``0`` corresponds to the first image channel). Must be used with multi-channel imags.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="labels" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">List of labels, separated by a comma. Labels *not* on this list will be excluded from consideration. Cannot be used in combination with ``exclude_labels``.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="exclude_labels" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation xml:lang="en">List of labels to be excluded from consideration, separated by a comma. The primary usage of this attribute is to exclude the background of a label image. Cannot be used in combination with ``labels``.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
<xs:complexType name="AssertHasJsonPropertyWithValue">
<xs:annotation>
<xs:documentation xml:lang="en"><![CDATA[
@@ -144,6 +144,7 @@
<tool file="sam_to_unsorted_bam.xml" />
<tool file="top_level_data.xml" />
<tool file="validation_hdf5.xml" />
<tool file="validation_image.xml"/>
<tool file="validation_zip.xml" />
<tool file="validation_tar.xml" />
<tool file="validation_tar_gz.xml" />
+182
View File
@@ -0,0 +1,182 @@
<tool id="validation_image" name="validation_image" version="1.0">
<command><![CDATA[
cp '$input' '$output'
]]></command>
<inputs>
<param name="input" type="data" format="data" />
</inputs>
<outputs>
<data name="output" format="data" />
</outputs>
<tests>
<!-- Tests with intensity images -->
<test>
<param name="input" value="im1_uint8.tif" />
<output name="output">
<assert_contents>
<has_image_width width="32" />
<has_image_height height="32" />
<has_image_channels channels="1" />
<has_image_center_of_mass center_of_mass="15.61, 15.48" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_width width="30" delta="2" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_width width="29" delta="2" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_width width="32" />
<has_image_height height="32" />
<has_image_channels channels="3" />
<has_image_center_of_mass channel="0" center_of_mass="7.5, 7.5" />
<has_image_mean_intensity channel="0" mean_intensity="0.25" />
<has_image_mean_intensity channel="1" mean_intensity="0.0" />
<has_image_mean_intensity channel="2" mean_intensity="0" />
<has_image_center_of_mass center_of_mass="7.5, 7.5" />
<has_image_mean_intensity mean_intensity="0.08333333333" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_mean_intensity channel="0" mean_intensity="0.24" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_mean_intensity channel="0" mean_intensity="0.24" eps="0.0100000001" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_mean_intensity channel="0" min="0.24" max="0.26" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_mean_intensity channel="0" max="0.24" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im3_b.tif" />
<output name="output">
<assert_contents>
<has_image_mean_intensity channel="0" min="0.26" />
</assert_contents>
</output>
</test>
<!-- Tests with label images -->
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_width width="32" />
<has_image_height height="32" />
<has_image_channels channels="1" />
<has_image_n_labels n="1" exclude_labels="0" />
<has_image_mean_object_size mean_object_size="256" exclude_labels="0" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_width width="32" />
<has_image_height height="32" />
<has_image_channels channels="1" />
<has_image_n_labels n="2" />
<has_image_mean_object_size mean_object_size="512" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size labels="0" mean_object_size="768" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size labels="0, 1" mean_object_size="512" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size mean_object_size="511" eps="0.9" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_width width="32" />
<has_image_height height="32" />
<has_image_channels channels="1" />
<has_image_n_labels n="2" />
<has_image_mean_object_size mean_object_size="511" eps="1.0" />
</assert_contents>
</output>
</test>
<test>
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size min="511" max="513" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size max="511" />
</assert_contents>
</output>
</test>
<test expect_test_failure="true">
<param name="input" value="im2_b.png" />
<output name="output">
<assert_contents>
<has_image_mean_object_size min="513" />
</assert_contents>
</output>
</test>
</tests>
</tool>