Commit 8b19e449 authored by Paul McCarthy's avatar Paul McCarthy
Browse files

Fixes and adjustments to fixlabels.load/saveLabelFile - ability to specify

labels which correspond to 'signal'.
parent 358f7b24
...@@ -62,8 +62,9 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -62,8 +62,9 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
- One or more labels for the component (multiple labels must be - One or more labels for the component (multiple labels must be
comma-separated). comma-separated).
- ``'True'`` if the component has been classified as *bad*, - ``'True'`` if the component has been classified as *bad*,
``'False'`` otherwise. ``'False'`` otherwise. This field is optional - if the last
comma-separated token on a line is not equal (case-insensitive)
to ``True`` or ``False``, it is interpreted as a component label.
The last line of the file contains the index (starting from 1) of all The last line of the file contains the index (starting from 1) of all
*bad* components, i.e. those components which are not classified as *bad* components, i.e. those components which are not classified as
...@@ -74,7 +75,7 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -74,7 +75,7 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
:arg includeLabel: If the file contains a single line containing a list :arg includeLabel: If the file contains a single line containing a list
component indices, this label will be used for the component indices, this label will be used for the
components in the list. Defaults to 'Unclassified components in the list. Defaults to 'Unclassified
noise' for FIX-like files, and 'Motion' for noise' for FIX-like files, and 'Movement' for
ICA-AROMA-like files. ICA-AROMA-like files.
:arg excludeLabel: If the file contains a single line containing component :arg excludeLabel: If the file contains a single line containing component
...@@ -88,7 +89,8 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -88,7 +89,8 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
the corresponding component. the corresponding component.
""" """
filename = op.abspath(filename) signalLabels = None
filename = op.abspath(filename)
with open(filename, 'rt') as f: with open(filename, 'rt') as f:
lines = f.readlines() lines = f.readlines()
...@@ -128,6 +130,8 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -128,6 +130,8 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
if excludeLabel is None: if excludeLabel is None:
if line[0] == '[': excludeLabel = 'Signal' if line[0] == '[': excludeLabel = 'Signal'
else: excludeLabel = 'Unknown' else: excludeLabel = 'Unknown'
else:
signalLabels = [excludeLabel]
# Remove any leading/trailing # Remove any leading/trailing
# whitespace or brackets. # whitespace or brackets.
...@@ -176,8 +180,11 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -176,8 +180,11 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
raise InvalidLabelFileError( raise InvalidLabelFileError(
'Invalid FIX classification file - ' 'Invalid FIX classification file - '
'line {}: {}'.format(i + 1, compLine)) 'line {}: {}'.format(i + 1, compLine))
compLabels = tokens[1:-1] if tokens[-1].lower() in ('true', 'false'):
compLabels = tokens[1:-1]
else:
compLabels = tokens[1:]
if compIdx != i + 1: if compIdx != i + 1:
raise InvalidLabelFileError( raise InvalidLabelFileError(
...@@ -193,9 +200,10 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -193,9 +200,10 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
for i, labels in enumerate(allLabels): for i, labels in enumerate(allLabels):
comp = i + 1 comp = i + 1
noise = isNoisyComponent(labels) noise = isNoisyComponent(labels, signalLabels)
if noise and (comp not in noisyComps): if noise and (comp not in noisyComps):
print(signalLabels)
raise InvalidLabelFileError('Noisy component {} has invalid ' raise InvalidLabelFileError('Noisy component {} has invalid '
'labels: {}'.format(comp, labels)) 'labels: {}'.format(comp, labels))
...@@ -203,7 +211,7 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -203,7 +211,7 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
i = comp - 1 i = comp - 1
labels = allLabels[i] labels = allLabels[i]
noise = isNoisyComponent(labels) noise = isNoisyComponent(labels, signalLabels)
if not noise: if not noise:
raise InvalidLabelFileError('Noisy component {} is missing ' raise InvalidLabelFileError('Noisy component {} is missing '
...@@ -212,24 +220,31 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None): ...@@ -212,24 +220,31 @@ def loadLabelFile(filename, includeLabel=None, excludeLabel=None):
return melDir, allLabels return melDir, allLabels
def saveLabelFile(allLabels, filename, dirname=None, listBad=True): def saveLabelFile(allLabels,
filename,
dirname=None,
listBad=True,
signalLabels=None):
"""Saves the given classification labels to the specified file. The """Saves the given classification labels to the specified file. The
classifications are saved in the format described in the classifications are saved in the format described in the
:func:`loadLabelFile` method. :func:`loadLabelFile` method.
:arg allLabels: A list of lists, one list for each component, where :arg allLabels: A list of lists, one list for each component, where
each list contains the labels for the corresponding each list contains the labels for the corresponding
component. component.
:arg filename: Name of the file to which the labels should be saved.
:arg filename: Name of the file to which the labels should be saved. :arg dirname: If provided, is output as the first line of the file.
Intended to be a relative path to the MELODIC analysis
directory with which this label file is associated.
:arg dirname: If provided, is output as the first line of the file. :arg listBad: If ``True`` (the default), the last line of the file
Intended to be a relative path to the MELODIC analysis will contain a comma separated list of components which
directory with which this label file is associated. are deemed 'noisy' (see :func:`isNoisyComponent`).
:arg listBad: If ``True`` (the default), the last line of the file :arg signalLabels: Labels which should be deemed 'signal' - see the
will contain a comma separated list of components which :func:`isNoisyComponent` function.
are deemed 'noisy' (see :func:`isNoisyComponent`).
""" """
lines = [] lines = []
...@@ -243,7 +258,7 @@ def saveLabelFile(allLabels, filename, dirname=None, listBad=True): ...@@ -243,7 +258,7 @@ def saveLabelFile(allLabels, filename, dirname=None, listBad=True):
for i, labels in enumerate(allLabels): for i, labels in enumerate(allLabels):
comp = i + 1 comp = i + 1
noise = isNoisyComponent(labels) noise = isNoisyComponent(labels, signalLabels)
# Make sure there are no # Make sure there are no
# commas in any label names # commas in any label names
...@@ -263,13 +278,20 @@ def saveLabelFile(allLabels, filename, dirname=None, listBad=True): ...@@ -263,13 +278,20 @@ def saveLabelFile(allLabels, filename, dirname=None, listBad=True):
f.write('\n'.join(lines) + '\n') f.write('\n'.join(lines) + '\n')
def isNoisyComponent(labels): def isNoisyComponent(labels, signalLabels=None):
"""Given a set of component labels, returns ``True`` if the component """Given a set of component labels, returns ``True`` if the component
is ultimately classified as noise, ``False`` otherwise. is ultimately classified as noise, ``False`` otherwise.
"""
labels = [l.lower() for l in labels] :arg signalLabels: Labels which are deemed signal. If a component has
noise = ('signal' not in labels) and ('unknown' not in labels) no labels in this list, it is deemed noise. Defaults
to ``['Signal', 'Unknown']`.
"""
if signalLabels is None:
signalLabels = ['signal', 'unknown']
signalLabels = [l.lower() for l in signalLabels]
labels = [l.lower() for l in labels]
noise = not any([sl in labels for sl in signalLabels])
return noise return noise
......
...@@ -14,7 +14,6 @@ import os.path as op ...@@ -14,7 +14,6 @@ import os.path as op
from . import image as fslimage from . import image as fslimage
from . import melodicanalysis as melanalysis from . import melodicanalysis as melanalysis
from . import melodiclabels as mellabels
class MelodicImage(fslimage.Image): class MelodicImage(fslimage.Image):
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment