Skip to content
Snippets Groups Projects
Commit a58ceca3 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

AtlasPanel refactoring. Is broken right now.

parent d155038f
No related branches found
No related tags found
No related merge requests found
...@@ -7,13 +7,17 @@ https://internal.fmrib.ox.ac.uk/i-wiki/Analysis/Todos/FSLView regularly, too. ...@@ -7,13 +7,17 @@ https://internal.fmrib.ox.ac.uk/i-wiki/Analysis/Todos/FSLView regularly, too.
* February 2015 internal release * February 2015 internal release
** Git release pipeline
** UI design ** UI design
** Atlas tools ** Atlas tools
** Histogram?
** SSH / VNC performance ** SSH / VNC performance
** Fix all the bugs ** Fix all the bugs
*** Command line *** Command line
*** Offscreen rendering *** Offscreen rendering
** DONE Git release pipeline
We now have an 'oxford' branch, which is linked to the jalapeno installation.
When you want to 'release' something, merge from the master branch to the
oxford branch, and push to jalapeno
* Things to do in props package * Things to do in props package
...@@ -102,6 +106,7 @@ perhaps into a standalone module... ...@@ -102,6 +106,7 @@ perhaps into a standalone module...
** DONE Graceful handling of bad input filenames ** DONE Graceful handling of bad input filenames
** DONE Aspect ratio on slicecanvas zoom, and panning is broken. ** DONE Aspect ratio on slicecanvas zoom, and panning is broken.
* Little things * Little things
** Ability to display vector data as directional (i.e. starting from voxel centre)
** Ortho canvases not taking up all the available space ** Ortho canvases not taking up all the available space
** 'Annotation' image type that allows the user to highlight regions in different colours. ** 'Annotation' image type that allows the user to highlight regions in different colours.
** Support ANALYZE75 ** Support ANALYZE75
......
...@@ -49,6 +49,7 @@ import os ...@@ -49,6 +49,7 @@ import os
import xml.etree.ElementTree as et import xml.etree.ElementTree as et
import os.path as op import os.path as op
import glob import glob
import collections
import logging import logging
import numpy as np import numpy as np
...@@ -67,28 +68,74 @@ if os.environ.get('FSLDIR', None) is None: ...@@ -67,28 +68,74 @@ if os.environ.get('FSLDIR', None) is None:
else: else:
ATLAS_DIR = op.join(os.environ['FSLDIR'], 'data', 'atlases') ATLAS_DIR = op.join(os.environ['FSLDIR'], 'data', 'atlases')
ATLAS_DESCRIPTIONS = collections.OrderedDict()
def listAtlases(): def listAtlases(refresh=False):
"""Returns a dictionary containing :class:`AtlasDescription` objects for """Returns a dictionary containing :class:`AtlasDescription` objects for
all available atlases. all available atlases.
:arg refresh: If ``True``, or if the atlas desriptions have not
previously been loaded, atlas descriptions are
loaded from the atlas files. Otherwise, prefviously
loaded descriptions are returned (see
:attr:`ATLAS_DESCRIPTIONS`).
""" """
if len(ATLAS_DESCRIPTIONS) == 0:
refresh = True
if not refresh:
return ATLAS_DESCRIPTIONS.values()
atlasFiles = glob.glob(op.join(ATLAS_DIR, '*.xml')) atlasFiles = glob.glob(op.join(ATLAS_DIR, '*.xml'))
atlasDescs = map(AtlasDescription, atlasFiles) atlasDescs = map(AtlasDescription, atlasFiles)
atlasDescs = sorted(atlasDescs, key=lambda d: d.name)
return {d.atlasID: d for d in atlasDescs} ATLAS_DESCRIPTIONS.clear()
for desc in atlasDescs:
ATLAS_DESCRIPTIONS[desc.atlasID] = desc
def loadAtlas(atlasDesc, loadSummary=False): return atlasDescs
if loadSummary or atlasDesc.atlasType == 'label':
return LabelAtlas(atlasDesc) def getAtlasDescription(atlasID):
"""Returns an :class:`AtlasDescription` instance describing the
atlas with the given ``atlasID``.
"""
if atlasDesc.atlasType == 'probabilistic': if len(ATLAS_DESCRIPTIONS) == 0:
return ProbabilisticAtlas(atlasDesc) listAtlases()
else:
raise ValueError('Unknown atlas type: {}'.format(atlasDesc.atlasType)) return ATLAS_DESCRIPTIONS[atlasID]
def loadAtlas(atlasID, loadSummary=False):
"""Loads and returns an :class:`Atlas` instance for the atlas
with the given ``atlasID``.
:arg loadSummary: If ``True``, a 3D :class:`LabelAtlas` image is
loaded. Otherwise, if the atlas is probabilistic,
a 4D :class:`ProbabilisticAtlas` image is loaded.
"""
if len(ATLAS_DESCRIPTIONS) == 0:
listAtlases()
atlasDesc = ATLAS_DESCRIPTIONS[atlasID]
# label atlases are only
# available in 'summary' form
if atlasDesc.atlasType == 'label':
loadSummary = True
if loadSummary: atlas = LabelAtlas( atlasDesc)
else: atlas = ProbabilisticAtlas(atlasDesc)
return atlas
class AtlasDescription(object): class AtlasDescription(object):
......
...@@ -48,6 +48,8 @@ titles = TypeDict({ ...@@ -48,6 +48,8 @@ titles = TypeDict({
'TimeSeriesPanel' : 'Time series', 'TimeSeriesPanel' : 'Time series',
'SpacePanel' : 'Space inspector', 'SpacePanel' : 'Space inspector',
'AtlasInfoPanel' : 'Atlas information',
'AtlasOverlayPanel' : 'Atlas overlays'
}) })
...@@ -88,10 +90,6 @@ labels = TypeDict({ ...@@ -88,10 +90,6 @@ labels = TypeDict({
'LocationPanel.volumeLabel' : 'Volume', 'LocationPanel.volumeLabel' : 'Volume',
'LocationPanel.spaceLabel' : 'Space', 'LocationPanel.spaceLabel' : 'Space',
'LocationPanel.outOfBounds' : 'Out of bounds', 'LocationPanel.outOfBounds' : 'Out of bounds',
'AtlasPanel.infoPanel' : 'Information',
'AtlasPanel.atlasListPanel' : 'Choose atlases',
'AtlasPanel.overlayPanel' : 'Choose overlays'
}) })
......
#!/usr/bin/env python
#
# atlasinfopanel.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import logging
import wx
import wx.html as wxhtml
import pwidgets.elistbox as elistbox
import fsl.fslview.panel as fslpanel
import fsl.data.atlases as atlases
log = logging.getLogger(__name__)
class AtlasListWidget(wx.Panel):
def __init__(self, parent, atlasPanel, atlasID):
wx.Panel.__init__(self, parent)
self.atlasID = atlasID
self.atlasPanel = atlasPanel
self.enableBox = wx.CheckBox(self)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.enableBox, flag=wx.EXPAND)
self.enableBox.Bind(wx.EVT_CHECKBOX, self.onEnable)
def onEnable(self, ev):
if self.enableBox.GetValue():
self.atlasPanel.enableAtlasInfo(self.atlasID)
else:
self.atlasPanel.disableAtlasInfo(self.atlasID)
# TODO
#
# Actions to show/hide atlas overlays are managed by the AtlasPanel,
# which provides methods to do so, and maintains the state required
# to track whether an overlay is enabled/disabled. Thec
# AtlasInfoPanel and AtlasOverlayPanel implement the GUI
# functionality, and the event handling needed to allow the user
# to toggle atlas information/overlays on/off, but management
# of the in-memory atlas images is handled by the AtlasPanel.
# Info panel, containing atlas-based regional
# proportions/labels for the current location
# Atlas list, containing a list of atlases
# that the user can choose from
class AtlasInfoPanel(fslpanel.FSLViewPanel):
def __init__(self, parent, imageList, displayCtx, atlasPanel):
fslpanel.FSLViewPanel.__init__(self, parent, imageList, displayCtx)
self.atlasPanel = atlasPanel
self.contentPanel = wx.SplitterWindow(self)
self.infoPanel = wxhtml.HtmlWindow(self.notebook)
self.atlasList = elistbox.EditableListBox(
self,
style=(elistbox.ELB_NO_ADD |
elistbox.ELB_NO_REMOVE |
elistbox.ELB_NO_MOVE))
for i, atlasDesc in enumerate(atlases.listAtlases()):
self.atlasList.Append(atlasDesc.name, atlasDesc.atlasID)
widget = AtlasListWidget(self.atlasList, atlasPanel, atlasDesc)
self.atlasList.SetItemWidget(i, widget)
# The info panel contains clickable links
# for the currently displayed regions -
# when a link is clicked, the location
# is centred at the corresponding region
self.infoPanel.Bind(wxhtml.EVT_HTML_LINK_CLICKED,
self._infoPanelLinkClicked)
displayCtx.addListener('location', self._name, self._locationChanged)
def _infoPanelLinkClicked(self, ev):
showType, atlasID, labelIndex = ev.GetLinkInfo().GetHref().split()
labelIndex = int(labelIndex)
atlas = self.enabledAtlases[atlasID]
label = atlas.desc.labels[labelIndex]
log.debug('{}/{} ({}) clicked'.format(atlasID, label.name, showType))
if showType == 'summary':
self.overlayPanel.toggleSummaryOverlay(atlas.desc)
elif showType == 'prob':
self.overlayPanel.toggleOverlay(atlas.desc, labelIndex, False)
elif showType == 'label':
self.overlayPanel.toggleOverlay(atlas.desc, labelIndex, True)
def _locationChanged(self, *a):
image = self._displayCtx.getSelectedImage()
display = self._displayCtx.getDisplayProperties(image)
loc = self._displayCtx.location
text = self.infoPanel
loc = transform.transform([loc], display.displayToWorldMat)[0]
if len(self.enabledAtlases) == 0:
text.SetPage(strings.messages['atlaspanel.chooseAnAtlas'])
return
if image.getXFormCode() != constants.NIFTI_XFORM_MNI_152:
text.SetPage(strings.messages['atlaspanel.notMNISpace'])
return
lines = []
titleTemplate = '<b>{}</b> (<a href="summary {} {}">Show/Hide</a>)'
labelTemplate = '{} (<a href="label {} {}">Show/Hide</a>)'
probTemplate = '{:0.2f}% {} (<a href="prob {} {}">Show/Hide</a>)'
for atlasID, atlas in self.enabledAtlases.items():
lines.append(titleTemplate.format(atlas.desc.name, atlasID, 0))
if isinstance(atlas, atlases.ProbabilisticAtlas):
proportions = atlas.proportions(loc)
for label, prop in zip(atlas.desc.labels, proportions):
if prop == 0.0:
continue
lines.append(probTemplate.format(prop,
label.name,
atlasID,
label.index,
atlasID,
label.index))
elif isinstance(atlas, atlases.LabelAtlas):
labelVal = atlas.label(loc)
label = atlas.desc.labels[int(labelVal)]
lines.append(labelTemplate.format(label.name,
atlasID,
label.index,
atlasID,
label.index))
text.SetPage('<br>'.join(lines))
#!/usr/bin/env python
#
# atlasoverlaypanel.py -
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
"""
"""
import logging
import wx
import numpy as np
import pwidgets.elistbox as elistbox
import fsl.data.atlases as atlases
import fsl.data.image as fslimage
import fsl.data.constants as constants
import fsl.fslview.panel as fslpanel
log = logging.getLogger(__name__)
class OverlayListWidget(wx.CheckBox):
def __init__(self, parent, atlasDesc, label=None):
wx.CheckBox.__init__(self, parent)
self.parent = parent
self.atlasDesc = atlasDesc
self.label = label
def _onCheck(self, ev):
pass
class AtlasOverlayPanel(fslpanel.FSLViewPanel):
def __init__(self, parent, imageList, displayCtx, atlasPanel):
fslpanel.FSLViewPanel.__init__(self, parent, imageList, displayCtx)
self.atlasPanel = atlasPanel
self.enabledOverlays = {}
self.atlasList = elistbox.EditableListBox(
self,
style=(elistbox.ELB_NO_ADD |
elistbox.ELB_NO_REMOVE |
elistbox.ELB_NO_MOVE))
self.regionPanel = wx.Panel( self)
self.regionFilter = wx.TextCtrl(self.regionPanel)
self.regionLists = [None] * len(atlasDescs)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.regionSizer = wx.BoxSizer(wx.VERTICAL)
self.sizer .Add(self.atlasList, flag=wx.EXPAND, proportion=1)
self.regionSizer.Add(self.regionFilter, flag=wx.EXPAND)
self.regionSizer.AddStretchSpacer()
self.sizer .Add(self.regionPanel, flag=wx.EXPAND, proportion=1)
self.regionPanel.SetSizer(self.regionSizer)
self .SetSizer(self.sizer)
for i, atlasDesc in enumerate(atlasDescs):
self.atlasList.Append(atlasDesc.name, atlasDesc)
self._updateAtlasState(i)
self.regionFilter.Bind(wx.EVT_TEXT, self._onRegionFilter)
self.atlasList.Bind(elistbox.EVT_ELB_SELECT_EVENT, self._onAtlasSelect)
self.regionSizer.Layout()
self.sizer .Layout()
def _onRegionFilter(self, ev):
filterStr = self.regionFilter.GetValue().lower()
for i, listBox in enumerate(self.regionLists):
if listBox is None:
continue
listBox.ApplyFilter(filterStr, ignoreCase=True)
self._updateAtlasState(i)
def _updateAtlasState(self, atlasIdx):
listBox = self.regionLists[atlasIdx]
if listBox is None:
weight = wx.FONTWEIGHT_LIGHT
colour = '#a0a0a0'
elif listBox.VisibleItemCount() == 0:
weight = wx.FONTWEIGHT_LIGHT
colour = '#303030'
else:
weight = wx.FONTWEIGHT_BOLD
colour = '#000000'
font = self.atlasList.GetItemFont(atlasIdx)
font.SetWeight(weight)
self.atlasList.SetItemFont(atlasIdx, font)
self.atlasList.SetItemForegroundColour(atlasIdx, colour, colour)
def _onAtlasSelect(self, ev):
atlasDesc = ev.data
atlasIdx = ev.idx
regionList = self.regionLists[atlasIdx]
if regionList is None:
regionList = elistbox.EditableListBox(
self.regionPanel,
style=(elistbox.ELB_NO_ADD |
elistbox.ELB_NO_REMOVE |
elistbox.ELB_NO_MOVE))
print 'Creating region list for {} ({})'.format(
atlasDesc.atlasID, id(regionList))
self.regionLists[atlasIdx] = regionList
for label in atlasDesc.labels:
regionList.Append(label.name)
filterStr = self.regionFilter.GetValue().lower()
regionList.ApplyFilter(filterStr, ignoreCase=True)
self._updateAtlasState(atlasIdx)
print 'Showing region list for {} ({})'.format(
atlasDesc.atlasID, id(regionList))
old = self.regionSizer.GetItem(1).GetWindow()
if old is not None:
old.Show(False)
regionList.Show(True)
self.regionSizer.Remove(1)
self.regionSizer.Insert(1, regionList, flag=wx.EXPAND, proportion=1)
self.regionSizer.Layout()
def overlayIsEnabled(self, atlasDesc, label=None, summary=False):
pass
def toggleSummaryOverlay(self, atlasDesc):
atlasID = atlasDesc.atlasID
overlayName = '{}/all'.format(atlasID)
overlay = self._imageList.find(overlayName)
if overlay is not None:
self._imageList.remove(overlay)
log.debug('Removed summary overlay {}'.format(overlayName))
else:
overlay = self.enabledAtlases.get(atlasID, None)
if overlay is None or \
isinstance(overlay, atlases.ProbabilisticAtlas):
overlay = atlases.loadAtlas(atlasDesc, True)
overlay.name = overlayName
# Even though all the FSL atlases
# are in MNI152 space, not all of
# their sform_codes are correctly set
overlay.nibImage.get_header().set_sform(
None, code=constants.NIFTI_XFORM_MNI_152)
self._imageList.append(overlay)
log.debug('Added summary overlay {}'.format(overlayName))
def toggleOverlay(self, atlasDesc, labelIndex, label):
"""
"""
atlasID = atlasDesc.atlasID
overlayName = '{}/{}'.format(atlasID,
atlasDesc.labels[labelIndex].name)
overlay = self._imageList.find(overlayName)
if overlay is not None:
self._imageList.remove(overlay)
log.debug('Removed overlay {}'.format(overlayName))
else:
atlas = self.enabledAtlases.get(atlasID, None)
if atlas is None or \
(label and isinstance(overlay, atlases.LabelAtlas)):
atlas = atlases.loadAtlas(atlasDesc, True)
if label:
if atlasDesc.atlasType == 'probabilistic':
labelVal = labelIndex + 1
elif atlasDesc.atlasType == 'label':
labelVal = labelIndex
mask = np.zeros(atlas.shape, dtype=np.uint8)
mask[atlas.data == labelIndex] = labelVal
else:
mask = atlas.data[..., labelIndex]
overlay = fslimage.Image(
mask,
header=atlas.nibImage.get_header(),
name=overlayName)
# See comment in toggleSummaryOverlay
overlay.nibImage.get_header().set_sform(
None, code=constants.NIFTI_XFORM_MNI_152)
if label:
overlay.imageType = 'mask'
self._imageList.append(overlay)
log.debug('Added overlay {}'.format(overlayName))
display = self._displayCtx.getDisplayProperties(overlay)
if label:
display.getDisplayOpts().colour = np.random.random(3)
else:
display.getDisplayOpts().cmap = 'hot'
...@@ -7,47 +7,27 @@ ...@@ -7,47 +7,27 @@
import logging import logging
import wx import wx
import wx.html as wxhtml import wx.html as wxhtml
import numpy as np import wx.lib.newevent as wxevent
import numpy as np
import pwidgets.elistbox as elistbox import pwidgets.elistbox as elistbox
import pwidgets.notebook as notebook import pwidgets.notebook as notebook
import fsl.utils.transform as transform import fsl.utils.transform as transform
import fsl.data.image as fslimage import fsl.data.image as fslimage
import fsl.data.atlases as atlases import fsl.data.atlases as atlases
import fsl.data.strings as strings import fsl.data.strings as strings
import fsl.data.constants as constants import fsl.data.constants as constants
import fsl.fslview.panel as fslpanel import fsl.fslview.panel as fslpanel
import fsl.fslview.controls.atlasoverlaypanel as atlasoverlaypanel
import fsl.fslview.controls.atlasinfopanel as atlasinfopanel
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class AtlasListWidget(wx.Panel):
def __init__(self, parent, atlasPanel, atlasDesc):
wx.Panel.__init__(self, parent)
self.atlasDesc = atlasDesc
self.atlasPanel = atlasPanel
self.enableBox = wx.CheckBox(self)
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.enableBox, flag=wx.EXPAND)
self.enableBox.Bind(wx.EVT_CHECKBOX, self.onEnable)
def onEnable(self, ev):
if self.enableBox.GetValue():
self.atlasPanel.enableAtlasInfo(self.atlasDesc.atlasID)
else:
self.atlasPanel.disableAtlasInfo(self.atlasDesc.atlasID)
class AtlasPanel(fslpanel.FSLViewPanel): class AtlasPanel(fslpanel.FSLViewPanel):
...@@ -55,6 +35,10 @@ class AtlasPanel(fslpanel.FSLViewPanel): ...@@ -55,6 +35,10 @@ class AtlasPanel(fslpanel.FSLViewPanel):
fslpanel.FSLViewPanel.__init__(self, parent, imageList, displayCtx) fslpanel.FSLViewPanel.__init__(self, parent, imageList, displayCtx)
self.atlasDescs = sorted(atlases.listAtlases(),
key=lambda d: d.name)
self.enabledAtlases = {}
self.notebook = notebook.Notebook(self) self.notebook = notebook.Notebook(self)
self.sizer = wx.BoxSizer(wx.HORIZONTAL) self.sizer = wx.BoxSizer(wx.HORIZONTAL)
...@@ -62,237 +46,39 @@ class AtlasPanel(fslpanel.FSLViewPanel): ...@@ -62,237 +46,39 @@ class AtlasPanel(fslpanel.FSLViewPanel):
self.SetSizer(self.sizer) self.SetSizer(self.sizer)
# Info panel, containing atlas-based regional # Temporary
# proportions/labels for the current location self.SetMaxSize((-1, 200))
self.infoPanel = wxhtml.HtmlWindow(self.notebook)
self.infoPanel.SetMinSize((-1, 100))
# Atlas list, containing a list of atlases self.atlasInfoPanel = atlasinfopanel.AtlasInfoPanel(
# that the user can choose from self.notebook, imageList, displayCtx, self)
self.atlasPanel = wx.Panel(self.notebook)
self.atlasFilter = wx.TextCtrl(self.atlasPanel)
self.atlasList = elistbox.EditableListBox(
self.atlasPanel,
style=(elistbox.ELB_NO_ADD |
elistbox.ELB_NO_REMOVE |
elistbox.ELB_NO_MOVE))
# Overlay panel, containing a list of regions, # Overlay panel, containing a list of regions,
# allowing the user to add/remove overlays # allowing the user to add/remove overlays
self.overlayPanel = wx.Panel(self.notebook) self.overlayPanel = atlasoverlaypanel.AtlasOverlayPanel(
self.notebook, imageList, displayCtx, self)
self.notebook.AddPage(self.infoPanel, self.notebook.AddPage(self.infoPanel,
strings.labels['AtlasPanel.infoPanel']) strings.labels[self.infoPanel])
self.notebook.AddPage(self.atlasPanel,
strings.labels['AtlasPanel.atlasListPanel'])
self.notebook.AddPage(self.overlayPanel, self.notebook.AddPage(self.overlayPanel,
strings.labels['AtlasPanel.overlayPanel']) strings.labels[self.overlayPanel])
self.notebook.ShowPage(0) self.notebook.ShowPage(0)
# The info panel contains clickable links
# for the currently displayed regions -
# when a link is clicked, the location
# is centred at the corresponding region
self.infoPanel.Bind(wxhtml.EVT_HTML_LINK_CLICKED,
self._infoPanelLinkClicked)
# Set up the atlas list, allowing the
# user to choose which atlases information
# (in the info panel) is shown for
self.atlasSizer = wx.BoxSizer(wx.VERTICAL)
self.atlasSizer.Add(self.atlasFilter, flag=wx.EXPAND)
self.atlasSizer.Add(self.atlasList, flag=wx.EXPAND, proportion=1)
self.atlasPanel.SetSizer(self.atlasSizer)
self.atlasFilter.Bind(wx.EVT_TEXT, self._onAtlasFilter)
self.atlasDescs = atlases.listAtlases()
self.enabledAtlases = {}
listItems = sorted(self.atlasDescs.items(), key=lambda (a, d): d.name)
for i, (atlasID, desc) in enumerate(listItems):
self.atlasList.Append(desc.name, atlasID)
widget = AtlasListWidget(self.atlasList, self, desc)
self.atlasList.SetItemWidget(i, widget)
displayCtx.addListener('location', self._name, self._locationChanged)
self.Layout() self.Layout()
def _infoPanelLinkClicked(self, ev):
showType, atlasID, labelIndex = ev.GetLinkInfo().GetHref().split()
labelIndex = int(labelIndex)
atlas = self.enabledAtlases[atlasID]
label = atlas.desc.labels[labelIndex]
log.debug('{}/{} ({}) clicked'.format(atlasID, label.name, showType))
if showType == 'summary':
self.toggleSummaryOverlay(atlasID)
elif showType == 'prob':
self.toggleOverlay(atlasID, labelIndex, False)
elif showType == 'label':
self.toggleOverlay(atlasID, labelIndex, True)
def _onAtlasFilter(self, ev):
filterStr = self.atlasFilter.GetValue().lower()
self.atlasList.ApplyFilter(filterStr, ignoreCase=True)
def enableAtlasInfo(self, atlasID): def enableAtlasInfo(self, atlasDesc):
desc = self.atlasDescs[atlasID]
atlasImage = atlases.loadAtlas(desc)
self.enabledAtlases[atlasID] = atlasImage atlasImage = atlases.loadAtlas(atlasDesc)
self.enabledAtlases[atlasDesc.atlasID] = atlasImage
self._locationChanged() self._locationChanged()
def disableAtlasInfo(self, atlasID): def disableAtlasInfo(self, atlasDesc):
self.enabledAtlases.pop(atlasID, None) self.enabledAtlases.pop(atlasDesc.atlasID, None)
self._locationChanged() self._locationChanged()
def toggleSummaryOverlay(self, atlasID):
overlayName = '{}/all'.format(atlasID)
overlay = self._imageList.find(overlayName)
if overlay is not None:
self._imageList.remove(overlay)
log.debug('Removed summary overlay {}'.format(overlayName))
else:
overlay = self.enabledAtlases.get(atlasID, None)
if overlay is None or \
isinstance(overlay, atlases.ProbabilisticAtlas):
overlay = atlases.loadAtlas(self.atlasDescs[atlasID], True)
overlay.name = overlayName
# Even though all the FSL atlases
# are in MNI152 space, not all of
# their sform_codes are correctly set
overlay.nibImage.get_header().set_sform(
None, code=constants.NIFTI_XFORM_MNI_152)
self._imageList.append(overlay)
log.debug('Added summary overlay {}'.format(overlayName))
def toggleOverlay(self, atlasID, labelIndex, label):
"""
"""
desc = self.atlasDescs[atlasID]
overlayName = '{}/{}'.format(atlasID, desc.labels[labelIndex].name)
overlay = self._imageList.find(overlayName)
if overlay is not None:
self._imageList.remove(overlay)
log.debug('Removed overlay {}'.format(overlayName))
else:
atlas = self.enabledAtlases.get(atlasID, None)
if atlas is None or \
(label and isinstance(overlay, atlases.LabelAtlas)):
atlas = atlases.loadAtlas(self.atlasDescs[atlasID], True)
if label:
if desc.atlasType == 'probabilistic':
labelVal = labelIndex + 1
elif desc.atlasType == 'label':
labelVal = labelIndex
mask = np.zeros(atlas.shape, dtype=np.uint8)
mask[atlas.data == labelIndex] = labelVal
else:
mask = atlas.data[..., labelIndex]
overlay = fslimage.Image(
mask,
header=atlas.nibImage.get_header(),
name=overlayName)
# See comment in toggleSummaryOverlay
overlay.nibImage.get_header().set_sform(
None, code=constants.NIFTI_XFORM_MNI_152)
if label:
overlay.imageType = 'mask'
self._imageList.append(overlay)
log.debug('Added overlay {}'.format(overlayName))
display = self._displayCtx.getDisplayProperties(overlay)
if label:
display.getDisplayOpts().colour = np.random.random(3)
else:
display.getDisplayOpts().cmap = 'hot'
def _locationChanged(self, *a):
image = self._displayCtx.getSelectedImage()
display = self._displayCtx.getDisplayProperties(image)
loc = self._displayCtx.location
text = self.infoPanel
loc = transform.transform([loc], display.displayToWorldMat)[0]
if len(self.enabledAtlases) == 0:
text.SetPage(strings.messages['atlaspanel.chooseAnAtlas'])
return
if image.getXFormCode() != constants.NIFTI_XFORM_MNI_152:
text.SetPage(strings.messages['atlaspanel.notMNISpace'])
return
lines = []
titleTemplate = '<b>{}</b> (<a href="summary {} {}">Show/Hide</a>)'
labelTemplate = '{} (<a href="label {} {}">Show/Hide</a>)'
probTemplate = '{:0.2f}% {} (<a href="prob {} {}">Show/Hide</a>)'
for atlasID, atlas in self.enabledAtlases.items():
lines.append(titleTemplate.format(atlas.desc.name, atlasID, 0))
if isinstance(atlas, atlases.ProbabilisticAtlas):
proportions = atlas.proportions(loc)
for label, prop in zip(atlas.desc.labels, proportions):
if prop == 0.0:
continue
lines.append(probTemplate.format(prop,
label.name,
atlasID,
label.index,
atlasID,
label.index))
elif isinstance(atlas, atlases.LabelAtlas):
labelVal = atlas.label(loc)
label = atlas.desc.labels[int(labelVal)]
lines.append(labelTemplate.format(label.name,
atlasID,
label.index,
atlasID,
label.index))
text.SetPage('<br>'.join(lines))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment