mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
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:
@@ -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,
|
||||
)
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user