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

MelodicClassification, and MCPanel code updated to be case

insensitive. Unrelated bugfix to AtlasInfoPanel.
parent d3c1f9c2
No related branches found
No related tags found
No related merge requests found
......@@ -212,7 +212,9 @@ class MelodicClassification(props.HasProperties):
clearComponents
.. note:: All component labels are converted to lower case.
.. note:: All component labels are internally stored as lower case;
their cased version (whatever is initially used) is accssible
via the :meth:`getDisplayLabel` method.
.. warning:: Do not modify the :attr:`labels` list directly - use the
......@@ -235,12 +237,18 @@ class MelodicClassification(props.HasProperties):
"""Create a ``MelodicClassification`` instance.
"""
self.__melimage = melimage
self.__ncomps = melimage.numComponents()
self.__melimage = melimage
self.__ncomps = melimage.numComponents()
self.__displayLabels = {}
self.clear()
def getDisplayLabel(self, label):
"""Returns the display name for the given label. """
return self.__displayLabels.get(label.lower(), label)
def clear(self):
"""Removes all labels from all components. """
......@@ -376,7 +384,13 @@ class MelodicClassification(props.HasProperties):
noise = not (self.hasLabel(comp, 'signal') or
self.hasLabel(comp, 'unknown'))
tokens = [str(comp + 1)] + self.getLabels(comp) + [str(noise)]
# Make sure there are no
# commas in any label names
labels = [self.getDisplayLabel(l) for l in self.getLabels(comp)]
labels = [l.replace(',', '_') for l in labels]
tokens = [str(comp + 1)] + labels + [str(noise)]
lines.append(', '.join(tokens))
......@@ -406,9 +420,10 @@ class MelodicClassification(props.HasProperties):
def addLabel(self, component, label):
"""Adds the given label to the given component. """
label = label.lower()
labels = list(self.labels[component])
comps = list(self.__components.get(label, []))
display = label
label = label.lower()
labels = list(self.labels[component])
comps = list(self.__components.get(label, []))
if label in labels:
return
......@@ -416,6 +431,8 @@ class MelodicClassification(props.HasProperties):
labels.append(label)
comps .append(component)
self.__displayLabels[label] = display
# Change __components first, so
# any listeners on labels are
# not notified before our intenral
......
......@@ -170,14 +170,19 @@ class AtlasInfoPanel(fslpanel.FSLEyesPanel):
text.SetPage(strings.messages['AtlasInfoPanel.chooseAnAtlas'])
return
opts = self._displayCtx.getOpts(overlay)
loc = self._displayCtx.location
loc = opts.transformCoords([loc], 'display', 'world')[0]
lines = []
if topText is not None:
lines.append(topText)
if overlay is None:
text.SetPage('<br>'.join(lines))
text.Refresh()
return
opts = self._displayCtx.getOpts(overlay)
loc = self._displayCtx.location
loc = opts.transformCoords([loc], 'display', 'world')[0]
# Three types of hyperlink:
# - one for complete (summary) label atlases,
......
......@@ -17,7 +17,6 @@ import pwidgets.widgetgrid as widgetgrid
import pwidgets.texttag as texttag
import fsl.fsleyes.panel as fslpanel
import fsl.fsleyes.colourmaps as fslcm
import fsl.fsleyes.displaycontext as fsldisplay
import fsl.data.melodicimage as fslmelimage
import fsl.data.strings as strings
......@@ -169,7 +168,6 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
tags = texttag.TextTagPanel(self.__grid,
style=(texttag.TTP_ALLOW_NEW_TAGS |
texttag.TTP_ADD_NEW_TAGS |
texttag.TTP_NO_DUPLICATES |
texttag.TTP_KEYBOARD_NAV))
......@@ -185,11 +183,32 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
tags.Bind(texttag.EVT_TTP_TAG_ADDED, self.__onTagAdded)
tags.Bind(texttag.EVT_TTP_TAG_REMOVED, self.__onTagRemoved)
self.__refreshTagOptions()
self.__refreshTags()
self.Layout()
def __refreshTagOptions(self):
"""Updates the options available on each :class:`.TextTagPanel`, from
the entries in the melodic classification :class:`.LookupTable`.
"""
overlay = self.__overlay
numComps = overlay.numComponents()
lut = self.__lut
displayLabels = [l.displayName() for l in lut.labels]
colours = [l.colour() for l in lut.labels]
for i in range(len(colours)):
colours[i] = [int(round(c * 255)) for c in colours[i]]
for comp in range(numComps):
tags = self.__grid.GetWidget(comp, 1)
tags.SetOptions(displayLabels, colours)
def __refreshTags(self):
"""Re-generates the tags on every :class:`.TextTagPanel` in the grid.
"""
......@@ -197,33 +216,17 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
overlay = self.__overlay
melclass = overlay.getICClassification()
numComps = overlay.numComponents()
lut = self.__lut
labels = [l.name() for l in lut.labels]
colours = [l.colour() for l in lut.labels]
# Compile lists of all the existing
# labels, and the colours for each one
for i in range(numComps):
for label in melclass.getLabels(i):
if label in labels:
continue
labels .append(label)
colours.append(fslcm.randomBrightColour())
for i in range(len(colours)):
colours[i] = [int(round(c * 255)) for c in colours[i]]
for row in range(numComps):
tags = self.__grid.GetWidget(row, 1)
tags.ClearTags()
tags.SetOptions(labels, colours)
for label in melclass.getLabels(row):
tags.AddTag(label)
tags.AddTag(melclass.getDisplayLabel(label))
self.__grid.FitInside()
def __onTagAdded(self, ev):
......@@ -232,22 +235,26 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
:class:`.MelodicClassification` instance.
"""
tags = ev.GetEventObject()
label = ev.tag
component = tags._melodicComponent
overlay = self.__overlay
lut = self.__lut
melclass = overlay.getICClassification()
tags = ev.GetEventObject()
label = ev.tag
comp = tags._melodicComponent
overlay = self.__overlay
lut = self.__lut
melclass = overlay.getICClassification()
log.debug('Label added to component {} ("{}")'.format(comp, label))
# Add the new label to the melodic component
melclass.disableListener('labels', self._name)
melclass.addLabel(component, label)
melclass.addLabel(comp, label)
# If the tag panel previously just contained
# the 'Unknown' tag, remove that tag
if tags.TagCount() == 2 and tags.HasTag('unknown'):
melclass.removeLabel(component, 'unknown')
tags.RemoveTag('unknown')
if tags.TagCount() == 2 and \
tags.HasTag('Unknown') and \
label.lower() != 'unknown':
melclass.removeLabel(comp, 'Unknown')
tags.RemoveTag('Unknown')
melclass.enableListener('labels', self._name)
......@@ -257,10 +264,14 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
colour = tags.GetTagColour(label)
colour = [c / 255.0 for c in colour]
log.debug('Adding new lookup table '
'entry for label {}'.format(label))
lut.disableListener('labels', self._name)
lut.new(name=label, colour=colour)
lut.enableListener('labels', self._name)
self.__refreshTagOptions()
self.__grid.FitInside()
......@@ -270,16 +281,18 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
:class:`.MelodicClassification` instance.
"""
tags = ev.GetEventObject()
label = ev.tag
component = tags._melodicComponent
overlay = self.__overlay
melclass = overlay.getICClassification()
tags = ev.GetEventObject()
label = ev.tag
comp = tags._melodicComponent
overlay = self.__overlay
melclass = overlay.getICClassification()
log.debug('Label removed from component {} ("{}")'.format(comp, label))
# Remove the label from
# the melodic component
melclass.disableListener('labels', self._name)
melclass.removeLabel(component, label)
melclass.removeLabel(comp, label)
melclass.enableListener('labels', self._name)
# If the tag panel now has no tags,
......@@ -299,6 +312,8 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
component = ev.row
opts = self._displayCtx.getOpts(self.__overlay)
log.debug('Grid row selected (component {})'.format(component))
opts.disableListener('volume', self._name)
opts.volume = component
opts.enableListener('volume', self._name)
......@@ -321,6 +336,8 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
grid = self.__grid
opts = self._displayCtx.getOpts(self.__overlay)
tags = grid.GetWidget(opts.volume, 1)
log.debug('Overlay volume changed ({})'.format(opts.volume))
grid.SetSelection(opts.volume, -1)
tags.FocusNewTagCtrl()
......@@ -330,14 +347,18 @@ class ComponentGrid(fslpanel.FSLEyesPanel):
"""Called when the :attr:`.MelodicClassification.labels` change.
Re-generates the tags shown on every :class:`.TextTagPanel`.
"""
log.debug('Melodic classification changed - '
'refreshing component grid tags')
self.__refreshTags()
def __lutChanged(self, *a):
"""Called when the :attr:`.LookupTable.labels` change.
Re-generates the tags shown on every :class:`.TextTagPanel`.
"""
self.__refreshTags()
Updates the options on every :class:`.TextTagPanel`.
"""
log.debug('Lookup table changed - refreshing '
'component grid tag options')
self.__refreshTagOptions()
class LabelGrid(fslpanel.FSLEyesPanel):
......@@ -391,7 +412,7 @@ class LabelGrid(fslpanel.FSLEyesPanel):
self._name,
self.__selectedOverlayChanged)
self.__overlay = None
self.__overlay = None
self.__recreateGrid()
self.__selectedOverlayChanged()
......@@ -474,7 +495,7 @@ class LabelGrid(fslpanel.FSLEyesPanel):
tags._label = label.name()
self.__grid.SetText( i, 0, label.name())
self.__grid.SetText( i, 0, label.displayName())
self.__grid.SetWidget(i, 1, tags)
tags.Bind(texttag.EVT_TTP_TAG_ADDED, self.__onTagAdded)
......@@ -521,6 +542,9 @@ class LabelGrid(fslpanel.FSLEyesPanel):
overlay = self.__overlay
melclass = overlay.getICClassification()
comp = int(ev.tag)
label = tags._label
log.debug('Component added to label {} ({})'.format(label, comp))
melclass.disableListener('labels', self._name)
......@@ -528,10 +552,11 @@ class LabelGrid(fslpanel.FSLEyesPanel):
# the other label is 'Unknown', remove the
# 'Unknown' label.
if len(melclass.getLabels(comp)) == 1 and \
melclass.hasLabel(comp, 'Unknown'):
melclass.removeLabel(comp, 'Unknown')
label != 'unknown' and \
melclass.hasLabel(comp, 'unknown'):
melclass.removeLabel(comp, 'unknown')
melclass.addComponent(tags._label, comp)
melclass.addComponent(label, comp)
melclass.enableListener('labels', self._name)
self.__refreshTags()
......@@ -547,10 +572,13 @@ class LabelGrid(fslpanel.FSLEyesPanel):
overlay = self.__overlay
melclass = overlay.getICClassification()
comp = int(ev.tag)
label = tags._label
log.debug('Component removed from label {} ({})'.format(label, comp))
melclass.disableListener('labels', self._name)
melclass.removeComponent(tags._label, comp)
melclass.removeComponent(label, comp)
# If the component has no more labels,
# give it an 'Unknown' label
......@@ -567,6 +595,9 @@ class LabelGrid(fslpanel.FSLEyesPanel):
"""
tags = self.__grid.GetWidget(ev.row, 1)
log.debug('Grid row selected (label "{}")'.format(tags._label))
tags.FocusNewTagCtrl()
......@@ -575,10 +606,13 @@ class LabelGrid(fslpanel.FSLEyesPanel):
Changes the current :attr:`.ImageOpts.volume` to the component
corresponding to the selected tag.
"""
tag = int(ev.tag)
overlay = self.__overlay
opts = self._displayCtx.getOpts(overlay)
log.debug('Tag selected on label grid: component {}'.format(tag))
opts.volume = tag
......@@ -595,5 +629,6 @@ class LabelGrid(fslpanel.FSLEyesPanel):
"""Called when the :attr:`.MelodicClassification.labels` change.
Re-populates the :class:`.WidgetGrid`.
"""
log.debug('Melodic classification changed - refreshing tags')
log.debug('Melodic classification changed - '
'refreshing label grid tags')
self.__refreshTags()
......@@ -74,12 +74,11 @@ class MelodicClassificationPanel(fslpanel.FSLEyesPanel):
self._displayCtx,
self.__lut)
# self.__labelGrid = melodicgrid.LabelGrid(
# self.__notebook,
# self._overlayList,
# self._displayCtx,
# self.__lut)
self.__labelGrid = wx.Panel(self.__notebook)
self.__labelGrid = melodicgrid.LabelGrid(
self.__notebook,
self._overlayList,
self._displayCtx,
self.__lut)
self.__loadButton = wx.Button(self)
self.__saveButton = wx.Button(self)
......@@ -211,15 +210,14 @@ class MelodicClassificationPanel(fslpanel.FSLEyesPanel):
# lookup table exists for all labels
for comp, labels in enumerate(melclass.labels):
for label in labels:
lutLabel = lut.getByName(label)
if lutLabel is not None:
print 'Label {} is already in lookup table'.format(label)
continue
print 'New melodic classification label: {}'.format(label)
log.debug('New melodic classification label: {}'.format(label))
lut.new(label)
label = melclass.getDisplayLabel(label)
lutLabel = lut.getByName(label)
if lutLabel is None:
log.debug('New melodic classification '
'label: {}'.format(label))
lut.new(label)
melclass.enableNotification('labels')
lut .enableNotification('labels')
......@@ -264,3 +262,11 @@ class MelodicClassificationPanel(fslpanel.FSLEyesPanel):
melclass = overlay.getICClassification()
melclass.clear()
melclass.disableNotification('labels')
for c in range(overlay.numComponents()):
melclass.addLabel(c, 'Unknown')
melclass.enableNotification('labels')
melclass.notify('labels')
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