Source code for smqtk.algorithms.image_io._interface

import abc

import numpy

from smqtk.algorithms import SmqtkAlgorithm
from smqtk.utils import ContentTypeValidator


[docs]class ImageReader (SmqtkAlgorithm, ContentTypeValidator): """ Interface for algorithms that load a raster image matrix from a data element. """ __slots__ = () @staticmethod def _get_matrix_property(data_element): """ Central method of getting and checking the matrix property of a DataElement. :param smqtk.representation.DataElement data_element: SMQTK DataElement instance. :raises AttributeError: If the element given does not have a ``matrix`` attribute. :raises AssertionError: If the element's matrix property does not match a None or ndarray value type. :return: Matrix property value if it is None or an ndarray. """ mat_prop = data_element.matrix assert mat_prop is None or isinstance(mat_prop, numpy.ndarray), \ "Element `matrix` property return should either be a matrix " \ "or None. Got {} instead.".format(type(mat_prop)) return mat_prop
[docs] def is_valid_element(self, data_element): """ Check if the given DataElement instance reports a content type that matches one of the MIME types reported by ``valid_content_types``. This override checks if the ``DataElement`` has the ``matrix`` property as the ``MatrixDataElement`` would provide, and that its value of an expected type. :param smqtk.representation.DataElement data_element: Data element instance to check. :return: True if the given element has a valid content type as reported by ``valid_content_types``, and False if not. :rtype: bool """ try: # If the given data element looks like a MatrixDataElement self._get_matrix_property(data_element) return True except AttributeError: # Otherwise proceed through traditional route. return super(ImageReader, self)\ .is_valid_element(data_element)
[docs] def load_as_matrix(self, data_element, pixel_crop=None): """ Load an image matrix from the given data element. **Matrix Property Shortcut.** If the given DataElement instance defines a ``matrix`` property this method simply returns that. This is intended to interface with instances of :py:class:`smqtk.representation.data_element.matrix.MatrixDataElement`. **Loading From Bytes.** When not loading from a short-cut matrix, matrix return format is ``ImageReader`` implementation dependant. Implementations of this interface should specify and describe their return type. Aside from the exceptions documented below, other exceptions may be raised when an image fails to load that are implementation dependent. :param smqtk.representation.DataElement data_element: DataElement to load image data from. :param None|smqtk.representation.AxisAlignedBoundingBox pixel_crop: Optional bounding box specifying a pixel sub-region to load from the given data. If this is provided it must represent a valid sub-region within the loaded image, otherwise a RuntimeError is raised. Handling of non-integer aligned boxes are implementation dependant. :raises RuntimeError: A crop region was specified but did not specify a valid sub-region of the image. :raises AssertionError: The ``data_element`` provided defined a ``matrix`` attribute/property, but its access did not result in an expected value. :raises ValueError: This error is raised when: - The given ``data_element`` was not of a valid content type. - A ``pixel_crop`` bounding box was provided but was zero volume. - ``pixel_crop`` bounding box vertices are not fully represented by integers. :return: Numpy ndarray of the image data. Specific return format is implementation dependant. :rtype: numpy.ndarray """ if pixel_crop: if pixel_crop.hypervolume == 0: raise ValueError("Volume of crop bounding box must be greater " "than 0. Given: {}".format(pixel_crop)) elif not issubclass(pixel_crop.dtype.type, numpy.integer): raise ValueError("Crop bounding box must be composed of " "integer coordinates. Given bounding box " "with dtype {}.".format(pixel_crop.dtype.type)) try: # If the given data element looks like a MatrixDataElement, simply # return the stored matrix property. return self._get_matrix_property(data_element) except AttributeError: # Any other data element type, attempt loading via plugin # implementation. self.raise_valid_element(data_element) return self._load_as_matrix(data_element, pixel_crop=pixel_crop)
@abc.abstractmethod def _load_as_matrix(self, data_element, pixel_crop=None): """ Internal method to be implemented that attempts loading an image from the given data element and returning it as an image matrix. Pre-conditions: - ``pixel_crop`` has a non-zero volume and is composed of integer types. :param smqtk.representation.DataElement data_element: DataElement to load image data from. :param None|smqtk.representation.AxisAlignedBoundingBox pixel_crop: Optional pixel crop region to load from the given data. If this is provided it must represent a valid sub-region within the loaded image, otherwise a RuntimeError is raised. :raises RuntimeError: A crop region was specified but did not specify a valid sub-region of the image. :return: Numpy ndarray of the image data. Specific return format is implementation dependant. :rtype: numpy.ndarray """
# TODO: ImageWriter interface