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)
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)
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
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)
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)
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)