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

Revamped fsl.py - more general, less tied to the Options -> Interface -> Run paradigm.

parent 9951e5ca
No related branches found
No related tags found
No related merge requests found
......@@ -15,12 +15,12 @@ import wx
# the latest version) - it calls logging.basicConfig(), and
# thus screws up our own logging. We overcome this by configuring
# the root logger before OpenGL.GL.shaders is imported (which
# occurs when fsl.tools.bet imports fsl.utils.ImageView).
# occurs when fsl.fslview.SliceCanvas is imported).
logging.basicConfig(
format='%(levelname)8s '\
'%(filename)20s '\
'%(lineno)4d: '\
'%(funcName)s - '\
format='%(levelname)8s '
'%(filename)20s '
'%(lineno)4d: '
'%(funcName)s - '
'%(message)s')
log = logging.getLogger('fsl')
......@@ -29,16 +29,93 @@ import fsl.utils.webpage as webpage
def getArgs():
def loadAllFSLTools():
"""
Looks in the fsl.tools package, loads a description for
every FSL tool present, and returns all descriptions in
a {toolName->toolObj} dictionary. See loadFSLTool.
"""
allTools = {}
for moduleName in dir(tools):
module = getattr(tools, moduleName)
try: fsltool = loadFSLTool(moduleName, module)
except TypeError: continue
allTools[moduleName] = fsltool
return allTools
def loadFSLTool(moduleName, module):
"""
Inspects the given module to see if it looks like a valid
FSL tool. If it is not, a TypeError is raised. If it is,
a container object is created and returned, containing
all of the elements of the tool.
"""
# Each FSL tool module may specify several things
toolName = getattr(module, 'FSL_TOOLNAME', None)
helpPage = getattr(module, 'FSL_HELPPAGE', 'index')
arguments = getattr(module, 'FSL_ARGUMENTS', None)
context = getattr(module, 'FSL_CONTEXT', None)
interface = getattr(module, 'FSL_INTERFACE', None)
actions = getattr(module, 'FSL_ACTIONS', [])
# But at the very least, must specify a name, and
# a function which will create an interface
if not all((toolName, interface)):
raise TypeError('"{}" does not appear to be a valid FSL tool'.format(
moduleName))
class FSLTool(object):
pass
fsltool = FSLTool()
fsltool.module = module
fsltool.moduleName = moduleName
fsltool.toolName = toolName
fsltool.helpPage = helpPage
fsltool.arguments = arguments
fsltool.context = context
fsltool.interface = interface
fsltool.actions = actions
return fsltool
def parseArgs(argv, allTools):
"""
Creates a command line ArgumentParser which will process general
arguments for fsl.py (this script) and, arguments for all FSL
tools which have defined their own command line arguments (see
loadFSLTool). Returns an object containing values for all of the
arguments that were passed in.
"""
parser = argparse.ArgumentParser()
parser.add_argument(
'toolname', help='Name of FSL tool to run')
parser.add_argument(
'-v', '--verbose', action='store_true', help='Verbose output')
return parser.parse_args()
subparser = parser.add_subparsers()
for moduleName, fslTool in allTools.items():
toolParser = subparser.add_parser(
moduleName, help='{} help'.format(fslTool.toolName))
toolParser.set_defaults(fslTool=fslTool)
if fslTool.arguments is not None:
fslTool.arguments(toolParser)
return parser.parse_args(argv)
def fslDirWarning(frame, toolName, fslEnvActive):
......@@ -57,92 +134,66 @@ def fslDirWarning(frame, toolName, fslEnvActive):
style=wx.OK | wx.ICON_EXCLAMATION).ShowModal()
def buildGUI(module, fslEnvActive):
# Each FSL tool module must specify several things
toolName = getattr(module, 'FSL_TOOLNAME', None)
helpPage = getattr(module, 'FSL_HELPPAGE', 'index')
options = getattr(module, 'FSL_OPTIONS', None)
interface = getattr(module, 'FSL_INTERFACE', None)
runtool = getattr(module, 'FSL_RUNTOOL', None)
if not all((toolName, options, interface)):
logging.error('"{}" does not appear to be a valid FSL tool'.format(
module.__name__))
sys.exit(1)
opts = options()
frame = wx.Frame(None, title='FSL -- {}'.format(toolName))
mainPanel = wx.Panel(frame)
buttonPanel = wx.Panel(mainPanel)
toolPanel = interface(mainPanel, opts)
runButton = wx.Button(buttonPanel, label='Run {}'.format(toolName))
helpButton = wx.Button(buttonPanel, label='Help')
quitButton = wx.Button(buttonPanel, label='Quit')
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
mainSizer = wx.BoxSizer(wx.VERTICAL)
def buildGUI(fslTool, toolCtx, fslEnvActive):
"""
"""
mainSizer.Add(toolPanel, flag=wx.EXPAND, proportion=1)
mainSizer.Add(buttonPanel, flag=wx.EXPAND)
frame = wx.Frame(None, title='FSL -- {}'.format(fslTool.toolName))
toolPanel = fslTool.interface(frame, ctx)
menuBar = wx.MenuBar()
fslMenu = wx.Menu()
frame.SetMenuBar(menuBar)
menuBar.Append(fslMenu, 'File')
buttonSizer.Add(runButton, flag=wx.EXPAND, proportion=1)
buttonSizer.Add(helpButton, flag=wx.EXPAND, proportion=1)
buttonSizer.Add(quitButton, flag=wx.EXPAND, proportion=1)
actions = []
if runtool is not None and fslEnvActive:
runButton.Bind(wx.EVT_BUTTON, lambda e: runtool(frame, opts))
else:
runButton.Enable(False)
actions.append((
wx.ID_HELP,
'{} Help'.format(fslTool.toolName),
lambda ev: webpage.openFSLHelp(fslTool.helpPage)))
if fslEnvActive:
helpButton.Bind(wx.EVT_BUTTON, lambda e: webpage.openFSLHelp(helpPage))
else:
helpButton.Enable(False)
for (name, func) in fslTool.actions:
actions.append((-1, name, lambda ev: func(frame, ctx)))
quitButton.Bind(wx.EVT_BUTTON, lambda e: frame.Destroy())
actions.append((
wx.ID_EXIT,
'Exit',
lambda ev: frame.Close()))
buttonPanel.SetSizer(buttonSizer)
mainPanel .SetSizer(mainSizer)
buttonSizer.Layout()
mainSizer .Layout()
for wxId, name, func in actions:
menuItem = fslMenu.Append(wxId, name)
frame.Bind(wx.EVT_MENU, func, menuItem)
buttonSizer.Fit(buttonPanel)
mainSizer .Fit(mainPanel)
frame .Fit()
toolPanel.Layout()
frame.Layout()
return frame
if __name__ == '__main__':
args = getArgs()
fsldir = os.environ.get('FSLDIR', None)
fslEnvActive = fsldir is not None
allTools = loadAllFSLTools()
args = parseArgs(sys.argv[1:], allTools)
fslTool = args.fslTool
if args.verbose:
log.setLevel(logging.DEBUG)
# Search in fsl.tools for the named module
toolname = args.toolname
toolmod = getattr(tools, toolname, None)
if toolmod is None:
log.error('Unknown tool: {}'.format(modname))
sys.exit(1)
fsldir = os.environ.get('FSLDIR', None)
fslEnvActive = fsldir is not None
if fslTool.context is not None: ctx = fslTool.context(args)
else: ctx = None
app = wx.App()
frame = buildGUI(toolmod, fslEnvActive)
frame = buildGUI(fslTool, ctx, fslEnvActive)
frame.Show()
wx.CallLater(1, fslDirWarning, frame, toolname, fslEnvActive)
wx.CallLater(1, fslDirWarning, frame, fslTool.toolName, fslEnvActive)
#import wx.lib.inspection
#wx.lib.inspection.InspectionTool().Show()
# import wx.lib.inspection
# wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
......@@ -629,15 +629,15 @@ class SliceCanvas(wxgl.GLCanvas):
ystride = glImageData.ystride
zstride = glImageData.zstride
# Figure out which slice we are drawing
zi = int(image.worldToVox(self.zpos, self.zax))
# Don't draw the slice if this
# image display is disabled
if not imageDisplay.enabled: continue
# Figure out which slice we are drawing,
# and if it's out of range, don't draw it
zi = int(image.worldToVox(self.zpos, self.zax))
if zi < 0 or zi >= zdim: continue
# nor if the display is disabled
if not imageDisplay.enabled: continue
# Set up the colour buffer
gl.glEnable(gl.GL_TEXTURE_1D)
gl.glActiveTexture(gl.GL_TEXTURE0)
......
......@@ -8,3 +8,4 @@
import bet
import feat
import flirt
import fslview
......@@ -311,6 +311,6 @@ def runBet(parent, opts):
FSL_TOOLNAME = 'BET'
FSL_HELPPAGE = 'bet'
FSL_OPTIONS = Options
FSL_CONTEXT = lambda args: Options()
FSL_INTERFACE = interface
FSL_RUNTOOL = runBet
FSL_ACTIONS = [('Run BET', runBet)]
......@@ -5,11 +5,8 @@
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
import sys
import wx
import fsl.fslview.slicecanvas as slicecanvas
import fsl.fslview.orthopanel as orthopanel
import fsl.fslview.imagelistpanel as imagelistpanel
......@@ -35,17 +32,21 @@ class FslViewPanel(wx.Panel):
self.Layout()
FSL_TOOLNAME = 'fslview'
def fslviewArguments(parser):
parser.add_argument('image', help='Image file to view', nargs='*')
if __name__ == '__main__':
def loadImages(args):
imageList = fslimage.ImageList(map(fslimage.Image, args.image))
return imageList
app = wx.App()
images = map(fslimage.Image, sys.argv[1:])
imageList = fslimage.ImageList(images)
frame = wx.Frame(None, title='fslview')
panel = FslViewPanel(frame, imageList)
def interface(parent, imageList):
panel = FslViewPanel(parent, imageList)
return panel
frame.Show()
app.MainLoop()
FSL_TOOLNAME = 'FSLView'
FSL_INTERFACE = interface
FSL_CONTEXT = loadImages
FSL_ARGUMENTS = fslviewArguments
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