class Thing(props.HasProperties):

        myobject     = props.Object()
        mybool       = props.Boolean()
        myint        = props.Int()
        myreal       = props.Real()
        mypercentage = props.Percentage()
        mystring     = props.String()
        mychoice     = props.Choice(('1', '2', '3', '4', '5'))
        myfilepath   = props.FilePath()
        mylist       = props.List()
        mycolour     = props.Colour()
        mycolourmap  = props.ColourMap()
        mybounds     = props.Bounds(ndims=2)
        mypoint      = props.Point(ndims=2)
        myarray      = props.Array()
Ejemplo n.º 2
0
class OverlayList(props.HasProperties):
    """Class representing a collection of overlays to be displayed together.

    Contains a :class:`props.properties_types.List` property called
    :attr:`overlays`, containing overlay objects (e.g. :class:`.Image` or
    :class:`.TriangleMesh` objects). Listeners can be registered on the
    ``overlays`` property, so they are notified when the overlay list changes.

    An :class:`OverlayList` object has a few wrapper methods around the
    :attr:`overlays` property, allowing the :class:`OverlayList` to be used as
    if it were a list itself.

    The :mod:`.loadoverlay` module contains some convenience functions for
    loading and adding overlays.

    The :meth:`getData` and :meth:`setData` methods allow arbitrary bits
    of data associated with an overlay to be stored and retrieved.
    """
    def __validateOverlay(self, atts, overlay):
        """Makes sure that the given overlay object is valid."""
        return (hasattr(overlay, 'name') and hasattr(overlay, 'dataSource'))

    overlays = props.List(listType=props.Object(
        allowInvalid=False, validateFunc=__validateOverlay))
    """A list of overlay objects to be displayed."""

    def __init__(self, overlays=None):
        """Create an ``OverlayList`` object from the given sequence of
        overlays."""

        if overlays is None: overlays = []
        self.overlays.extend(overlays)

        # The append/insert methods allow an initial
        # overlay type to be specified for newly
        # added overlays. This can be queried via
        # the initOverlayType method (and is done so
        # by DisplayContext instances).
        self.__initOverlayType = {}

        # This dictionary may be used throughout FSLeyes,
        # via the getData/setData methods, to store
        # any sort of data associated with an overlay.
        # It is a dict of dicts:
        #
        #   {
        #      overlay : {
        #        key : value,
        #        key : value,
        #      },
        #      overlay : {
        #        key : value,
        #        key : value,
        #      }
        #   }
        self.__overlayData = weakref.WeakKeyDictionary()

    def initOverlayType(self, overlay):
        """Returns the initial type for the given ``overlay``, if it was
        specified via the :meth:`append` or :meth:`insert` methods. Returns
        ``None`` otherwise.
        """
        return self.__initOverlayType.get(overlay, None)

    def getData(self, overlay, key, *args):
        """Returns any stored value associated with the specified ``overlay``
        and ``key``.

        :arg default: Default value if there is no value associated with the
                      given ``key``. If not specified, and an unknown key is
                      given, a ``KeyError`` is raised.
        """
        if len(args) not in (0, 1):
            raise RuntimeError('Invalid arguments: {}'.format(args))

        ovlDict = self.__overlayData.get(overlay, {})

        if len(args) == 1:
            return ovlDict.get(key, args[0])
        else:
            return ovlDict[key]

    def setData(self, overlay, key, value):
        """Stores the given value via the specified ``overlay`` and ``key``.
        """
        ovlDict = self.__overlayData.get(overlay, None)

        if ovlDict is not None:
            ovlDict[key] = value
        else:
            self.__overlayData[overlay] = {key: value}

    def find(self, name):
        """Returns the first overlay with the given ``name`` or ``dataSource``,
        or ``None`` if there is no overlay with said ``name``/``dataSource``.
        """

        if name is None:
            return None

        absname = op.abspath(name)

        for overlay in self.overlays:

            if overlay.name == name:
                return overlay

            if overlay.dataSource is None:
                continue

            # Ignore file extensions for NIFTI images.
            if isinstance(overlay, fslimage.Image):
                if fslimage.removeExt(overlay.dataSource) == \
                   fslimage.removeExt(absname):
                    return overlay
            else:
                if overlay.dataSource == absname:
                    return overlay

        return None

    def __str__(self):
        return self.overlays.__str__()

    def __repr__(self):
        return self.overlays.__str__()

    # Wrappers around the overlays list property, allowing this
    # OverlayList object to be used as if it is actually a list.
    def __len__(self):
        return self.overlays.__len__()

    def __getitem__(self, key):
        return self.overlays.__getitem__(key)

    def __iter__(self):
        return self.overlays.__iter__()

    def __contains__(self, item):
        return self.overlays.__contains__(item)

    def __setitem__(self, key, val):
        return self.overlays.__setitem__(key, val)

    def __delitem__(self, key):

        if isinstance(key, slice): pass
        elif isinstance(key, int): key = slice(key, key + 1, None)
        else: raise IndexError('Invalid key type')

        ovls = self[key]
        for ovl in ovls:
            self.__initOverlayType.pop(ovl, None)

        return self.overlays.__delitem__(key)

    def index(self, item):
        return self.overlays.index(item)

    def count(self, item):
        return self.overlays.count(item)

    def append(self, item, overlayType=None):

        with props.suppress(self, 'overlays', notify=True):

            self.overlays.append(item)

            if overlayType is not None:
                self.__initOverlayType[item] = overlayType

    def extend(self, iterable, overlayTypes=None):

        with props.suppress(self, 'overlays', notify=True):

            result = self.overlays.extend(iterable)

            if overlayTypes is not None:
                for overlay, overlayType in overlayTypes.items():
                    self.__initOverlayType[overlay] = overlayType

        return result

    def pop(self, index=-1):
        ovl = self.overlays.pop(index)
        self.__initOverlayType.pop(ovl, None)
        return ovl

    def move(self, from_, to):
        return self.overlays.move(from_, to)

    def remove(self, item):
        self.__initOverlayType.pop(item, None)
        self.overlays.remove(item)

    def insert(self, index, item, overlayType=None):

        with props.suppress(self, 'overlays', notify=True):

            self.overlays.insert(index, item)

            if overlayType is not None:
                self.__initOverlayType[item] = overlayType

    def insertAll(self, index, items):
        return self.overlays.insertAll(index, items)