From 36ac17474add6c623a1a3cd35d0a81f7169eaa60 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauld.mccarthy@gmail.com>
Date: Wed, 14 Oct 2015 16:05:48 +0100
Subject: [PATCH] OrthoPanel.__init__ now takes a boolean flag, allowing
 toolbars to be toggled. Bet, feat, flirt tools now working.

---
 fsl/fsleyes/views/orthopanel.py |  19 ++-
 fsl/tools/bet.py                |  70 ++++++-----
 fsl/tools/feat.py               | 205 ++++++++++++++++++++------------
 fsl/tools/flirt.py              | 132 ++++++++++++--------
 4 files changed, 264 insertions(+), 162 deletions(-)

diff --git a/fsl/fsleyes/views/orthopanel.py b/fsl/fsleyes/views/orthopanel.py
index c75be4e30..5ae778dac 100644
--- a/fsl/fsleyes/views/orthopanel.py
+++ b/fsl/fsleyes/views/orthopanel.py
@@ -122,12 +122,14 @@ class OrthoPanel(canvaspanel.CanvasPanel):
     """
 
 
-    def __init__(self, parent, overlayList, displayCtx):
+    def __init__(self, parent, overlayList, displayCtx, addToolbars=True):
         """Create an ``OrthoPanel``.
 
         :arg parent:      The :mod:`wx` parent.
         :arg overlayList: An :class:`.OverlayList` instance.
         :arg displayCtx:  A :class:`.DisplayContext` instance.
+        :arg addToolbars: If ``False``, the toolbars (listed above) are not
+                          added. Defaults to ``True``.
         """
 
         sceneOpts = orthoopts.OrthoOpts()
@@ -246,7 +248,7 @@ class OrthoPanel(canvaspanel.CanvasPanel):
         # The ViewPanel AuiManager seems to
         # struggle if we add these toolbars
         # immediately, so we'll do it asynchronously 
-        def addToolbars():
+        def _addToolbars():
             self.togglePanel(overlaydisplaytoolbar.OverlayDisplayToolBar,
                              viewPanel=self)
             self.togglePanel(orthotoolbar.OrthoToolBar,
@@ -254,7 +256,8 @@ class OrthoPanel(canvaspanel.CanvasPanel):
             self.togglePanel(orthoedittoolbar.OrthoEditToolBar,
                              ortho=self) 
 
-        wx.CallAfter(addToolbars)
+        if addToolbars:
+            wx.CallAfter(_addToolbars)
 
 
     def destroy(self):
@@ -812,7 +815,10 @@ class OrthoFrame(wx.Frame):
         ctx, dummyCanvas = fslgl.getWXGLContext() 
         fslgl.bootstrap()
         
-        self.panel = OrthoPanel(self, overlayList, displayCtx)
+        self.panel = OrthoPanel(self,
+                                overlayList,
+                                displayCtx,
+                                addToolbars=False)
         self.Layout()
 
         if dummyCanvas is not None:
@@ -852,7 +858,10 @@ class OrthoDialog(wx.Dialog):
         ctx, dummyCanvas = fslgl.getWXGLContext()
         fslgl.bootstrap()
         
-        self.panel = OrthoPanel(self, overlayList, displayCtx)
+        self.panel = OrthoPanel(self,
+                                overlayList,
+                                displayCtx,
+                                addToolbars=False)
         self.Layout()
 
         if dummyCanvas is not None:
diff --git a/fsl/tools/bet.py b/fsl/tools/bet.py
index f5f54f22b..7d026c910 100644
--- a/fsl/tools/bet.py
+++ b/fsl/tools/bet.py
@@ -4,10 +4,12 @@
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
+"""This module implements a GUI front end to the FSL BET tool. """
 
-from collections import OrderedDict
+import numpy as np
 
 import props
+props.initGUI()
 
 # The colour maps module must be initialised
 # before the displaycontext module can be loaded
@@ -16,26 +18,33 @@ colourmaps.init()
 
 import fsl.data.image               as fslimage
 import fsl.utils.transform          as transform
+import fsl.fsleyes.overlay          as fsloverlay
 import fsl.fsleyes.displaycontext   as displaycontext
 import fsl.fsleyes.gl               as fslgl
 
-runChoices = OrderedDict((
+
+runChoices = [' ', '-R', '-S', '-B', '-Z', '-F', '-A', '-A2']
+
+
+runChoiceLabels = {
 
     # This is a bit silly, but we can't use an empty
     # string as a key here, due to the way that props
     # handles empty strings.
-    (' ',   'Run standard brain extraction using bet2'),
-    ('-R',  'Robust brain centre estimation (iterates bet2 several times)'),
-    ('-S',  'Eye & optic nerve cleanup (can be useful in SIENA)'),
-    ('-B',  'Bias field & neck cleanup (can be useful in SIENA)'),
-    ('-Z',  'Improve BET if FOV is very small in Z'),
-    ('-F',  'Apply to 4D FMRI data'),
-    ('-A',  'Run bet2 and then betsurf to get additional skull and scalp '
-            'surfaces'),
-    ('-A2', 'As above, when also feeding in non-brain extracted T2')))
+    ' '   : 'Run standard brain extraction using bet2',
+    '-R'  : 'Robust brain centre estimation (iterates bet2 several times)',
+    '-S'  : 'Eye & optic nerve cleanup (can be useful in SIENA)',
+    '-B'  : 'Bias field & neck cleanup (can be useful in SIENA)',
+    '-Z'  : 'Improve BET if FOV is very small in Z',
+    '-F'  : 'Apply to 4D FMRI data',
+    '-A'  : 'Run bet2 and then betsurf to get additional skull and scalp '
+            'surfaces',
+    '-A2' : 'As above, when also feeding in non-brain extracted T2'}
 
 
 class Options(props.HasProperties):
+    """The ``Options`` class contains all of the options  required to run BET.
+    """
 
     inputImage           = props.FilePath(
         exists=True,
@@ -65,8 +74,7 @@ class Options(props.HasProperties):
 
 
     def setOutputImage(self, value, valid, *a):
-        """
-        When a (valid) input image file name is selected, the output
+        """When a (valid) input image file name is selected, the output
         image is set to the same name, with a suffix of '_brain'.
         """
 
@@ -76,8 +84,7 @@ class Options(props.HasProperties):
 
         
     def clearT2Image(self, value, *a):
-        """
-        This is a bit of a hack. If the user provides an invalid value
+        """This is a bit of a hack. If the user provides an invalid value
         for the T2 image (when running bet with the -A2 flag), but then
         changes their run choice to something other than -A2 (meaning
         that the invalid T2 image won't actually be used, so the fact
@@ -90,17 +97,14 @@ class Options(props.HasProperties):
 
 
     def __init__(self):
-        """
-        Adds a few callback listeners for various bits of behaviour.
-        """
+        """Adds a few callback listeners for various bits of behaviour. """
 
         self.addListener('inputImage', 'setOutputImage', self.setOutputImage)
         self.addListener('runChoice',  'clearT2Image',   self.clearT2Image)
 
 
     def genBetCmd(self):
-        """
-        Generates a command line call to the bet shell script, from
+        """Generates a command line call to the bet shell script, from
         the current option values.
         """
 
@@ -185,8 +189,7 @@ optTooltips = {
 
 
 def selectHeadCentre(opts, button):
-    """
-    Pops up a little dialog window allowing the user to interactively
+    """Pops up a little dialog window allowing the user to interactively
     select the head centre location.
     """
     import                                 wx
@@ -197,17 +200,19 @@ def selectHeadCentre(opts, button):
     fslgl.bootstrap()
 
     image      = fslimage.Image(opts.inputImage)
-    imageList  = fslimage.ImageList([image])
+    imageList  = fsloverlay.OverlayList([image])
     displayCtx = displaycontext.DisplayContext(imageList)
-    display    = displayCtx.getDisplay(image)
+    display    = displayCtx.getDisplay(image, overlayType='volume')
+    volOpts    = display.getDisplayOpts()
     parent     = button.GetTopLevelParent()
     frame      = orthopanel.OrthoDialog(parent,
                                         imageList,
                                         displayCtx,
                                         opts.inputImage,
-                                        style=wx.RESIZE_BORDER)
-    v2dMat     = display.getTransform('voxel',   'display')
-    d2vMat     = display.getTransform('display', 'voxel')
+                                        style=(wx.DEFAULT_DIALOG_STYLE |
+                                               wx.RESIZE_BORDER))
+    v2dMat     = volOpts.getTransform('voxel',   'display')
+    d2vMat     = volOpts.getTransform('display', 'voxel')
 
     # Whenever the x/y/z coordinates change on
     # the ortho panel, update the option values.
@@ -233,6 +238,10 @@ def selectHeadCentre(opts, button):
     voxCoords           = [opts.xCoordinate,
                            opts.yCoordinate,
                            opts.zCoordinate]
+
+    if voxCoords == [0, 0, 0]:
+        voxCoords = np.array(image.shape[:3]) / 2
+    
     worldCoords         = transform.transform([voxCoords], v2dMat)[0]
     displayCtx.location = worldCoords
 
@@ -249,7 +258,7 @@ betView = props.NotebookGroup((
             'inputImage',
             'outputImage',
             'fractionalIntensity',
-            'runChoice',
+            props.Widget('runChoice', labels=runChoiceLabels),
             props.Widget('t2Image', visibleWhen=lambda i: i.runChoice == '-A2')
         )),
     props.VGroup(
@@ -276,6 +285,7 @@ betView = props.NotebookGroup((
 
 
 def interface(parent, args, opts):
+    """Generates the BET gui. """
     
     import wx
     
@@ -290,6 +300,7 @@ def interface(parent, args, opts):
 
 
 def runBet(parent, opts):
+    """Runs BET using the specified options. """
 
     import fsl.utils.runwindow          as runwindow
     import fsl.fsleyes.views.orthopanel as orthopanel 
@@ -304,8 +315,7 @@ def runBet(parent, opts):
 
         inImage   = fslimage.Image(opts.inputImage)
         outImage  = fslimage.Image(opts.outputImage)
-        imageList = fslimage.ImageList([inImage, outImage])
-
+        imageList = fsloverlay.OverlayList([inImage, outImage])
         displayCtx = displaycontext.DisplayContext(imageList)
         outDisplay = displayCtx.getDisplay(outImage)
         outOpts    = outDisplay.getDisplayOpts()
diff --git a/fsl/tools/feat.py b/fsl/tools/feat.py
index e430d3a46..759335e5a 100644
--- a/fsl/tools/feat.py
+++ b/fsl/tools/feat.py
@@ -1,81 +1,124 @@
 #!/usr/bin/env python
 #
-# feat.py - 
+# feat.py - FEAT front end.
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
+"""This module implements a non-functional front end to the FSL FEAT tool. """
 
 
-from collections import OrderedDict
-
 import props
-
-analysisTypeOpts = OrderedDict((
-    ('firstLevel', 'First-level analysis'),
-    ('highLevel',  'Higher-level analysis')))
-
-analysisStageOpts = OrderedDict((
-    ('full',       'Full analysis'),
-    ('pre',        'Pre-stats'),
-    ('pre-stats',  'Pre-stats + Stats'),
-    ('stats',      'Stats'),
-    ('stats-post', 'Stats + Post-stats'),
-    ('post',       'Post-stats'),
-    ('reg',        'Registration only')))
-
-highLevelInputTypes = OrderedDict((
-    ('featDirs',   'Inputs are lower-level FEAT directories'),
-    ('copeImages', 'Inputs are 3D cope images from FEAT directories')))
-
-sliceTimingOpts = OrderedDict((
-    ('none',       'None'),
-    ('regup',      'Regular up (0, 1, 2, ..., n-1)'),
-    ('regdown',    'Regular down (n-1, n-2, ..., 0'),
-    ('int',        'Interleaved (0, 2, 4, ..., 1, 3, 5, ...)'),
-    ('orderFile',  'Use slice order file'),
-    ('timingFile', 'Use slice timings file')))
-
-perfusionOpts = OrderedDict((
-    ('tag',     'First timepoint is tag'),
-    ('control', 'First timepoint is control')))
-
-motionParameterOpts = OrderedDict((
-    ('none',     "Don't Add Motion Parameters"),
-    ('standard', "Standard Motion Parameters"),
-    ('extended', "Standard + Extended Motion Parameters")))
-
-effectModellingOpts = OrderedDict((
-    ('fixed',  'Fixed effects'),
-    ('ols',    'Mixed effects: Simple OLS'),
-    ('flame1', 'Mixed effects: FLAME 1'),
-    ('flame2', 'Mixed effects: FLAME 1+2')))
-
-zRenderingOpts = OrderedDict((
-    ('actual', 'Use actual Z min/max'),
-    ('preset', 'Use preset Z min/max')))
-
-blobOpts = OrderedDict((
-    ('solid',       'Solid blobs'),
-    ('transparent', 'Transparent blobs')))
-
-regSearchOpts = OrderedDict((
-    ('none',   'No search'),
-    ('normal', 'Normal search'),
-    ('full',   'Full search')))
-
-regDofOpts = OrderedDict((
-    ('3',  '3 DOF'),
-    ('6',  '6 DOF'),
-    ('7',  '7 DOF'),
-    ('9',  '9 DOF'),
-    ('12', '12 DOF')))
-
-regStructDofOpts = OrderedDict((
-    ('3',   '3 DOF'),
-    ('6',   '6 DOF'),
-    ('7',   '7 DOF'),
-    ('BBR', 'BBR'),
-    ('12',  '12 DOF')))
+props.initGUI()
+
+analysisTypeOpts = ['firstLevel',
+                    'highLevel']
+analysisTypeOptLabels = {
+    'firstLevel' : 'First-level analysis',
+    'highLevel'  : 'Higher-level analysis'}
+
+analysisStageOpts = ['full',
+                     'pre',
+                     'pre-stats',
+                     'stats', 
+                     'stats-post',
+                     'post',
+                     'reg']
+analysisStageOptLabels = {
+    'full'       : 'Full analysis',
+    'pre'        : 'Pre-stats',
+    'pre-stats'  : 'Pre-stats + Stats',
+    'stats'      : 'Stats',
+    'stats-post' : 'Stats + Post-stats',
+    'post'       : 'Post-stats',
+    'reg'        : 'Registration only'}
+
+highLevelInputTypes = ['featDirs',
+                       'copeImages']
+highLevelInputTypeLabels = {
+    'featDirs'   : 'Inputs are lower-level FEAT directories',
+    'copeImages' : 'Inputs are 3D cope images from FEAT directories'}
+
+sliceTimingOpts = ['none',
+                   'regup',
+                   'regdown',
+                   'int',
+                   'orderFile',
+                   'timingFile']
+sliceTimingOptLabels = {
+    'none'       : 'None',
+    'regup'      : 'Regular up (0, 1, 2, ..., n-1)',
+    'regdown'    : 'Regular down (n-1, n-2, ..., 0',
+    'int'        : 'Interleaved (0, 2, 4, ..., 1, 3, 5, ...)',
+    'orderFile'  : 'Use slice order file',
+    'timingFile' : 'Use slice timings file'}
+
+perfusionOpts = ['tag',
+                 'control']
+perfusionOptLabels = {
+    'tag'     : 'First timepoint is tag',
+    'control' : 'First timepoint is control'}
+
+motionParameterOpts = ['none',
+                       'standard',
+                       'extended']
+motionParameterOptLabels = {
+    'none'     : "Don't Add Motion Parameters",
+    'standard' : "Standard Motion Parameters",
+    'extended' : "Standard + Extended Motion Parameters"}
+
+effectModellingOpts = ['fixed',
+                       'ols',
+                       'flame1',
+                       'flame2']
+effectModellingOptLabels = {
+    'fixed'  : 'Fixed effects',
+    'ols'    : 'Mixed effects: Simple OLS',
+    'flame1' : 'Mixed effects: FLAME 1',
+    'flame2' : 'Mixed effects: FLAME 1+2'}
+
+zRenderingOpts = ['actual',
+                  'preset']
+zRenderingOptLabels = {
+    'actual' : 'Use actual Z min/max',
+    'preset' : 'Use preset Z min/max'}
+
+blobOpts = ['solid',
+            'transparent']
+blobOptLabels = {
+    'solid'       : 'Solid blobs',
+    'transparent' : 'Transparent blobs'}
+
+regSearchOpts = ['none',
+                 'normal',
+                 'full']
+regSearchOptLabels = {
+    'none'   : 'No search',
+    'normal' : 'Normal search',
+    'full'   : 'Full search'}
+
+regDofOpts = ['3',
+              '6',
+              '7',
+              '9',
+              '12']
+regDofOptLabels = {
+    '3'  : '3 DOF',
+    '6'  : '6 DOF',
+    '7'  : '7 DOF',
+    '9'  : '9 DOF',
+    '12' : '12 DOF'}
+
+regStructDofOpts = ['3',
+                    '6',
+                    '7',
+                    'BBR',
+                    '12']
+regStructDofOptLabels = {
+    '3'   : '3 DOF',
+    '6'   : '6 DOF',
+    '7'   : '7 DOF',
+    'BBR' : 'BBR',
+    '12'  : '12 DOF'}
                 
 
 class Options(props.HasProperties):
@@ -358,7 +401,7 @@ dataView = props.VGroup(
         props.VGroup(
             visibleWhen=lambda i: i.analysisType == 'highLevel',
             children=(
-                'inputDataType',
+                props.Widget('inputDataType', labels=highLevelInputTypeLabels),
                 props.Widget(
                     'higherLevelFeatInput',
                     visibleWhen=lambda i: i.inputDataType == 'featDirs'),
@@ -385,7 +428,7 @@ prestatsView = props.VGroup(
                 'b0_TE',
                 'b0_unwarpDir',
                 'b0_signalLossThreshold')),
-        'sliceTimingCorrection',
+        props.Widget('sliceTimingCorrection', labels=sliceTimingOptLabels),
         props.Widget(
             'sliceTimingFile',
             visibleWhen=lambda i: i.sliceTimingCorrection == 'timingFile'),
@@ -401,6 +444,7 @@ prestatsView = props.VGroup(
             children=(
                 'perfusionSubtraction',
                 props.Widget('perfusionOption',
+                             labels=perfusionOptLabels,
                              visibleWhen=lambda i: i.perfusionSubtraction))),
         'temporalHighpass',
         'melodic'))
@@ -410,7 +454,7 @@ statsView = props.VGroup(
     enabledWhen=lambda i: tabEnabled(i, 'Stats'),
     children=(
         'useFILMPrewhitening',
-        'addMotionParameters',
+        props.Widget('addMotionParameters', labels=motionParameterOptLabels),
         'voxelwiseConfoundList',
         'applyExternalScript',
         'addAdditionalConfounds',
@@ -442,14 +486,14 @@ postStatsView = props.VGroup(
             border=True,
             visibleWhen=lambda i: i.thresholding != 'None',
             children=(
-                'renderZMinMax',
+                props.Widget('renderZMinMax', labels=zRenderingOptLabels),
                 props.Widget(
                     'renderZMin',
                     visibleWhen=lambda i: i.renderZMinMax == 'preset'),
                 props.Widget(
                     'renderZMax',
                     visibleWhen=lambda i: i.renderZMinMax == 'preset'),
-                'blobTypes'))))
+                props.Widget('blobTypes', labels=blobOptLabels)))))
 
 regView = props.VGroup(
     label='Registration',
@@ -460,7 +504,9 @@ regView = props.VGroup(
             label='Functional -> Expanded functional',
             border=True,
             visibleWhen=lambda i: i.expandedFunctionalImage is not None,
-            children=('functionalSearch', 'functionalDof')),
+            children=(
+                props.Widget('functionalSearch', labels=regSearchOptLabels),
+                props.Widget('functionalDof', labels=regDofOptLabels))),
         'mainStructuralImage',
         props.HGroup(
             label='Functional -> Structural',
@@ -473,7 +519,9 @@ regView = props.VGroup(
             border=True,
             visibleWhen=lambda i: i.standardSpaceImage is not None,
             children=(
-                props.HGroup(('standardSearch', 'standardDof')),
+                props.HGroup((
+                    props.Widget('standardSearch', labels=regSearchOptLabels),
+                    props.Widget('standardDof', labels=regDofOptLabels))),
                 props.HGroup((
                     'nonLinearReg',
                     props.Widget(
@@ -482,8 +530,9 @@ regView = props.VGroup(
 
 
 featView = props.VGroup((
-    'analysisType',
+    props.Widget('analysisType', labels=analysisTypeOptLabels),
     props.Widget('analysisStages',
+                 labels=analysisStageOptLabels,
                  enabledWhen=lambda i: i.analysisType == 'firstLevel'),
     props.NotebookGroup((
         miscView,
diff --git a/fsl/tools/flirt.py b/fsl/tools/flirt.py
index 20f497913..609252fa2 100644
--- a/fsl/tools/flirt.py
+++ b/fsl/tools/flirt.py
@@ -4,49 +4,76 @@
 #
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
+"""This module implements a non-functional front end to the FSL flirt tool.
+"""
 
-from collections import OrderedDict
 
 import props
-
-flirtModes = OrderedDict((
-    ('single',   'Input image -> Reference image'),
-    ('multiple', 'Low res image -> High res image -> Reference image')))
-
-
-modelDOFChoices = OrderedDict((
-    ('rigid3',    'Rigid Body (3 parameter model)'),
-    ('translate', 'Translation Only (3 parameter model)'),
-    ('rigid6',    'Rigid Body (6 parameter model)'),
-    ('rescale',   'Global Rescale (7 parameter model)'),
-    ('trad',      'Traditional (9 parameter model)'),
-    ('affine',    'Affine (12 parameter model)')))
-
-
-searchModes = OrderedDict((
-    ('nosearch',  'Already virtually aligned (no search)'),
-    ('orient',    'Not aligned, but same orientation'),
-    ('misorient', 'Incorrectly oriented')))
-
-
-costFunctions = OrderedDict((
-    ('correlation',     'Correlation Ratio'),
-    ('mutualinfo',      'Mutual Information'),
-    ('normmutualinfo',  'Normalised Mutual Information'),
-    ('normcorrelation', 'Normalised Correlation (intra-modal)'),
-    ('leastsquares',    'Least Squares (intra-modal)')))
-
-interpolationMethods = OrderedDict((
-    ('trilinear', 'Tri-Linear'),
-    ('nn',        'Nearest Neighbour'),
-    ('spline',    'Spline'),
-    ('sinc',      'Sinc')))
-
-
-sincWindowOpts = OrderedDict((
-    ('rect',     'Rectangular'),
-    ('hanning',  'Hanning'),
-    ('blackman', 'Blackman')))
+props.initGUI()
+
+flirtModes           = ['single',
+                        'multiple']
+modelDOFChoices      = ['rigid3',  
+                        'translate',
+                        'rigid6',  
+                        'rescale', 
+                        'trad',    
+                        'affine']
+searchModes          = ['nosearch',
+                        'orient',
+                        'misorient']
+costFunctions        = ['correlation',   
+                        'mutualinfo',    
+                        'normmutualinfo',
+                        'normcorrelation',
+                        'leastsquares']
+interpolationMethods = ['trilinear',
+                        'nn',
+                        'spline',
+                        'sinc']
+sincWindowOpts       = ['rect',
+                        'hanning',
+                        'blackman']
+
+
+flirtModeLabels = {
+    'single'   : 'Input image -> Reference image',
+    'multiple' : 'Low res image -> High res image -> Reference image'}
+
+
+modelDOFChoiceLabels = {
+    'rigid3'    : 'Rigid Body (3 parameter model)',
+    'translate' : 'Translation Only (3 parameter model)',
+    'rigid6'    : 'Rigid Body (6 parameter model)',
+    'rescale'   : 'Global Rescale (7 parameter model)',
+    'trad'      : 'Traditional (9 parameter model)',
+    'affine'    : 'Affine (12 parameter model)'}
+
+
+searchModeLabels = {
+    'nosearch'  : 'Already virtually aligned (no search)',
+    'orient'    : 'Not aligned, but same orientation',
+    'misorient' : 'Incorrectly oriented'}
+
+
+costFunctionLabels = {
+    'correlation'     : 'Correlation Ratio',
+    'mutualinfo'      : 'Mutual Information',
+    'normmutualinfo'  : 'Normalised Mutual Information',
+    'normcorrelation' : 'Normalised Correlation (intra-modal)',
+    'leastsquares'    : 'Least Squares (intra-modal)'}
+
+interpolationMethodLabels = {
+    'trilinear' : 'Tri-Linear',
+    'nn'        : 'Nearest Neighbour',
+    'spline'    : 'Spline',
+    'sinc'      : 'Sinc'}
+
+
+sincWindowOptLabels = {
+    'rect'     : 'Rectangular',
+    'hanning'  : 'Hanning',
+    'blackman' : 'Blackman'}
 
 
 def inSingleMode(  opts): return opts.flirtMode == 'single'
@@ -101,7 +128,7 @@ tooltips = None
 searchOptions    = props.VGroup(
     label='Search',
     children=(
-        'searchMode',
+        props.Widget('searchMode', labels=searchModeLabels),
         props.HGroup(('searchAngleXMin', 'searchAngleXMax'),
                      visibleWhen=lambda i: i.searchMode != 'nosearch'),
         props.HGroup(('searchAngleYMin', 'searchAngleYMax'),
@@ -112,7 +139,7 @@ searchOptions    = props.VGroup(
 costFuncOptions  = props.VGroup(
     label='Cost Function',
     children=(
-        'costFunction',
+        props.Widget('costFunction', labels=costFunctionLabels),
         props.Widget(
             'costHistBins',
             visibleWhen=lambda i: i.costFunction in ['correlation',
@@ -122,8 +149,9 @@ costFuncOptions  = props.VGroup(
 interpOptions = props.VGroup(
     label='Interpolation',
     children=(
-        'interpolation',
-        props.VGroup(('sincWindow', 'sincWindowWidth'),
+        props.Widget('interpolation', labels=interpolationMethodLabels),
+        props.VGroup((props.Widget('sincWindow', labels=sincWindowOptLabels),
+                      'sincWindowWidth'),
                      visibleWhen=lambda i: i.interpolation == 'sinc')))
 
 weightVolOptions = props.VGroup(
@@ -133,14 +161,20 @@ weightVolOptions = props.VGroup(
         'weightingInput'))
 
 flirtView = props.VGroup((
-    'flirtMode',
+    props.Widget('flirtMode', labels=flirtModeLabels),
     'refImage',
-    props.Widget('inputImage',  visibleWhen=inSingleMode),
-    props.Widget('inToRefMode', visibleWhen=inSingleMode), 
+    props.Widget('inputImage', visibleWhen=inSingleMode),
+    props.Widget('inToRefMode',
+                 labels=modelDOFChoiceLabels,
+                 visibleWhen=inSingleMode), 
     props.Widget('hiResImage',  visibleWhen=inMultipleMode),
-    props.Widget('hiToRefMode', visibleWhen=inMultipleMode),
+    props.Widget('hiToRefMode',
+                 labels=modelDOFChoiceLabels,
+                 visibleWhen=inMultipleMode),
     props.Widget('loResImage',  visibleWhen=inMultipleMode),
-    props.Widget('loToHiMode',  visibleWhen=inMultipleMode), 
+    props.Widget('loToHiMode',
+                 labels=modelDOFChoiceLabels,
+                 visibleWhen=inMultipleMode), 
     'outputImage',
     'sndyImages',
     props.NotebookGroup(label='Advanced Options',
-- 
GitLab