示例#1
0
    def getOverlayName(self, atlasID, labelIdx, summary):
        """Returns a name to be used for the specified atlas (see the section
        on :ref:`atlas names <atlas-panel-overlay-names>`).

        :arg atlasID:  Atlas identifier

        :arg labelIdx: Label index, or ``None`` for a complete atlas.

        :arg summary:  ``True`` corresponds to a label atlas, ``False`` to a
                       probabilistic atlas.
        """
        atlasDesc = atlases.getAtlasDescription(atlasID)

        if atlasDesc.atlasType == 'summary' or labelIdx is None:
            summary = True

        if summary: overlayType = 'label'
        else: overlayType = 'prob'

        if labelIdx is None:
            overlayName = '{}/{}/all'.format(atlasID, overlayType)
        else:
            overlayName = '{}/{}/{}'.format(atlasID, overlayType,
                                            atlasDesc.labels[labelIdx].name)

        return overlayName, summary
    def __init__(self,
                 parent,
                 atlasID,
                 atlasPanel,
                 atlasOvlPanel,
                 labelIdx=None):
        """Create an ``OverlayListWidget``.

        :arg parent:        The :mod:`wx` parent object - this is assumed to
                            be an :class:`.EditableListBox`.

        :arg atlasID:       The atlas identifier.

        :arg atlasOvlPanel: The :class:`AtlasOverlayPanel` which created this
                            ``OverlayListWidget``.

        :arg atlasPanel:    The :class:`.AtlasPanel` which owns the
                            :class:`AtlasOverlayPanel` that created this
                            ``OverlayListWidget``.

        :arg labelIdx:      Label index of the region, if this
                            ``OverlatyListWidget`` corresponds to a region,
                            or ``None``  if it corresponds to an atlas.
        """

        wx.Panel.__init__(self, parent)

        self.__atlasID = atlasID
        self.__atlasDesc = atlases.getAtlasDescription(atlasID)
        self.__atlasPanel = atlasPanel
        self.__atlasOvlPanel = atlasOvlPanel
        self.__atlasList = parent
        self.__labelIdx = labelIdx

        self.__enableBox = wx.CheckBox(self)
        self.__enableBox.SetValue(False)

        self.__sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.SetSizer(self.__sizer)

        self.__sizer.Add(self.__enableBox, flag=wx.EXPAND)

        self.__enableBox.Bind(wx.EVT_CHECKBOX, self.__onEnable)

        if labelIdx is not None:
            self.__locateButton = wx.Button(self,
                                            label='+',
                                            style=wx.BU_EXACTFIT)
            self.__sizer.Add(self.__locateButton, flag=wx.EXPAND)

            self.__locateButton.Bind(wx.EVT_BUTTON, self.__onLocate)
示例#3
0
    def __overlayListChanged(self, *a):
        """Called when the :class:`.OverlayList` changes.

        Makes sure that the :class:`.AtlasOverlayPanel` state is up to date -
        see the :meth:`.AtlasOverlayPanel.setOverlayState` method.
        """

        for overlayName in list(self.__enabledOverlays.keys()):

            overlay, atlasID, labelIdx, summary = \
                self.__enabledOverlays[overlayName]

            if overlay not in self.overlayList:

                self.__enabledOverlays.pop(overlayName)
                atlasDesc = atlases.getAtlasDescription(atlasID)
                self.__overlayPanel.setOverlayState(atlasDesc, labelIdx,
                                                    summary, False)
示例#4
0
    def locateRegion(self, atlasID, labelIdx):
        """Moves the :attr:`.DisplayContext.location`  to the specified
        region in the specified atlas. See the :class:`.AtlasDescription`
        class for details on atlas identifiers/label indices.

        :arg atlasID:  Atlas identifier
        :arg labelIdx: Label index
        """

        atlasDesc = atlases.getAtlasDescription(atlasID)
        label = atlasDesc.labels[labelIdx]
        overlay = self.displayCtx.getReferenceImage(
            self.displayCtx.getSelectedOverlay())

        if overlay is None:
            log.warn('No reference image available - cannot locate region')

        opts = self.displayCtx.getOpts(overlay)
        worldLoc = (label.x, label.y, label.z)
        dispLoc = opts.transformCoords([worldLoc], 'world', 'display')[0]

        self.displayCtx.location.xyz = dispLoc
示例#5
0
    def toggleOverlay(self,
                      atlasID,
                      labelIdx,
                      summary,
                      onLoad=None,
                      onError=None):
        """Adds or removes the specified overlay to/from the
        :class:`.OverlayList`.

        :arg onLoad:  Optional function to be called when the overlay has been
                      added/removed.

        :arg onError: Optional function to be called if an error occurs while
                      loading an overlay.

        See :meth:`getOverlayName` for details on the other arguments.
        """

        atlasDesc = atlases.getAtlasDescription(atlasID)
        overlayName, summary = self.getOverlayName(atlasID, labelIdx, summary)
        overlay = self.overlayList.find(overlayName)

        if overlay is not None:

            self.overlayList.disableListener('overlays', self.name)
            self.overlayList.remove(overlay)
            self.overlayList.enableListener('overlays', self.name)

            self.__enabledOverlays.pop(overlayName, None)
            self.__overlayPanel.setOverlayState(atlasDesc, labelIdx, summary,
                                                False)

            log.debug('Removed overlay {}'.format(overlayName))

            if onLoad is not None:
                onLoad()
            return

        def realOnLoad(atlas):
            initprops = {}
            # label image
            if labelIdx is None:
                overlay = fslimage.Image(atlas)
                initprops['overlayType'] = 'label'

            else:

                # regional label image
                if summary:
                    overlay = atlas.get(index=labelIdx, binary=False)
                    initprops['overlayType'] = 'mask'
                    initprops['colour'] = np.random.random(3)

                # regional statistic/probability image
                else:
                    overlay = atlas.get(index=labelIdx)
                    initprops['overlayType'] = 'volume'
                    initprops['cmap'] = 'hot'
                    initprops['displayRange'] = (atlasDesc.lower,
                                                 atlasDesc.upper)
                    initprops['clippingRange'] = (atlasDesc.lower,
                                                  atlasDesc.upper)

            overlay.name = overlayName

            with props.suppress(self.overlayList, 'overlays', self.name):
                self.overlayList.append(overlay, **initprops)

            self.__overlayPanel.setOverlayState(atlasDesc, labelIdx, summary,
                                                True)

            self.__enabledOverlays[overlayName] = (overlay, atlasID, labelIdx,
                                                   summary)

            log.debug('Added overlay {}'.format(overlayName))

            if onLoad is not None:
                onLoad()

        self.loadAtlas(atlasID, summary, onLoad=realOnLoad, onError=onError)
示例#6
0
    def loadAtlas(self,
                  atlasID,
                  summary,
                  onLoad=None,
                  onError=None,
                  matchResolution=True):
        """Loads the atlas image with the specified ID. The atlas is loaded
        asynchronously (via the :mod:`.idle` module), as it can take some
        time. Use the `onLoad` argument if you need to do something when the
        atlas has been loaded.

        :arg onLoad:          Optional. A function which is called when the
                              atlas has been loaded, and which is passed the
                              loaded :class:`.Atlas` image.

        :arg onError:         Optional. A function which is called if the
                              atlas loading job raises an error. Passed the
                              ``Exception`` that was raised.

        :arg matchResolution: If ``True`` (the default), the version of the
                              atlas with the most suitable resolution, based
                              on the current contents of the
                              :class:`.OverlayList`, is loaded.

        See the :func:`.atlases.loadAtlas` function for details on the other
        arguments.
        """

        # Get the atlas description, and the
        # most suitable resolution to load.
        desc = atlases.getAtlasDescription(atlasID)
        res = self.__getSuitableResolution(desc, matchResolution)

        if desc.atlasType == 'label':
            summary = True

        atlas = self.__loadedAtlases.get((atlasID, summary, res), None)

        if atlas is None:

            log.debug('Loading atlas {}/{}'.format(
                atlasID, 'label' if summary else 'prob'))

            status.update('Loading atlas {}...'.format(atlasID), timeout=None)

            def load():

                # the panel might get destroyed
                # before this function is called
                if self.destroyed:
                    return

                atlas = atlases.loadAtlas(atlasID, summary, resolution=res)

                # The atlas panel may be destroyed
                # before the atlas is loaded.
                if not self or self.destroyed:
                    return

                self.__loadedAtlases[atlasID, summary, res] = atlas

                status.update('Atlas {} loaded.'.format(atlasID))

                if onLoad is not None:
                    idle.idle(onLoad, atlas)

            idle.run(load, onError=onError)

        # If the atlas has already been loaded,
        # pass it straight to the onload function
        elif onLoad is not None:
            onLoad(atlas)
示例#7
0
    def toggleOverlay(self,
                      atlasID,
                      labelIdx,
                      summary,
                      onLoad=None,
                      onError=None):
        """Adds or removes the specified overlay to/from the
        :class:`.OverlayList`.

        :arg onLoad:  Optional function to be called when the overlay has been
                      added/removed.

        :arg onError: Optional function to be called if an error occurs while
                      loading an overlay.

        See :meth:`getOverlayName` for details on the other arguments.
        """

        atlasDesc = atlases.getAtlasDescription(atlasID)
        overlayName, summary = self.getOverlayName(atlasID, labelIdx, summary)
        overlay = self.overlayList.find(overlayName)

        if overlay is not None:

            self.overlayList.disableListener('overlays', self.name)
            self.overlayList.remove(overlay)
            self.overlayList.enableListener('overlays', self.name)

            self.__enabledOverlays.pop(overlayName, None)
            self.__overlayPanel.setOverlayState(atlasDesc, labelIdx, summary,
                                                False)

            log.debug('Removed overlay {}'.format(overlayName))

            if onLoad is not None:
                onLoad()
            return

        def realOnLoad(atlas):
            # label image
            if labelIdx is None:
                overlayType = 'label'
                data = atlas[:]

            else:

                # regional label image
                if summary:

                    labelVal = atlasDesc.find(index=labelIdx).value
                    overlayType = 'mask'
                    data = np.zeros(atlas.shape, dtype=np.uint16)
                    data[atlas[:] == labelVal] = labelVal

                # regional probability image
                else:
                    overlayType = 'volume'
                    data = atlas[:, :, :, labelIdx]

            overlay = fslimage.Image(data,
                                     header=atlas.header,
                                     name=overlayName)

            with props.suppress(self.overlayList, 'overlays', self.name):
                self.overlayList.append(overlay, overlayType=overlayType)

            self.__overlayPanel.setOverlayState(atlasDesc, labelIdx, summary,
                                                True)

            self.__enabledOverlays[overlayName] = (overlay, atlasID, labelIdx,
                                                   summary)

            log.debug('Added overlay {}'.format(overlayName))

            display = self.displayCtx.getDisplay(overlay)
            display.overlayType = overlayType
            opts = display.opts

            if overlayType == 'mask': opts.colour = np.random.random(3)
            elif overlayType == 'volume': opts.cmap = 'hot'

            if onLoad is not None:
                onLoad()

        self.loadAtlas(atlasID, summary, onLoad=realOnLoad, onError=onError)