Commit 932037fd authored by Taylor Hanayik's avatar Taylor Hanayik
Browse files

remove bet_gui and console entry

parent 64cd57c6
#!/usr/bin/env python
import sys
import argparse
from collections import OrderedDict
import wx
import yaml
from fsl.utils import idle
import fsleyes_props as props
import fsl.gui.core as core
import fsl.gui.views as fslViews
import fsl.gui.tools as fslTools
class Bet(props.HasProperties):
"""
Bet is the data model for Bet Gui
"""
betRunChoices = OrderedDict((
('default', 'Default Brain extraction'),
('robust', 'Robust'),
('eyeClean', 'Eye and optic nerve cleanup'),
('biasAndNeckClean', 'Bias field and neck Clean'),
('smallZ', 'Brain has small Z FOV'),
('4d', 'Apply to 4D fMRI'),
('withBetSurf', 'Also run betsurf'),
('withBetSurfT2', 'Run betsurf with additional T2 image')
))
inputFile = props.FilePath(required=True, exists=True)
outputFile = props.FilePath(required=True, exists=False)
fval = props.Real(precision=0.001, minval=0, maxval=1, clamped=True)
betRunType = props.Choice(choices=list(betRunChoices.values()))
def __init__(
self,
**kwargs
):
super().__init__(**kwargs)
def main():
# get an app instance
app = wx.App()
bet = Bet()
betView = core.loadSpec(fslViews.bet)
gui = core.buildGUI(betView, bet)
app.MainLoop()
if __name__ == "__main__":
sys.exit(main())
"""
tools are models that store data and allow FSL tools to be called from other python scripts
"""
#!/usr/bin/env python
#
# bet_model.py
#
# Author: Taylor Hanayik <hanayik@gmail.com>
import os
import subprocess
from collections import OrderedDict
from fsl.utils import idle
import fsleyes_props as props
class Bet(object):
"""
A BetModel contains the data and methods necessary to setup and run FSL's bet tool.
The BetModel can be queried and properties can be set via a controller of a GUI view object
"""
bet_type_choices = {
'default': '',
'robust': '-R',
'eye and optic nerve cleanup': '-S',
'bias field and neck cleanup': '-B',
'small z field of view': '-Z',
'apply 4D': '-F',
'bet + betsurf': '-A',
'bet + betsurf with additional T2w image': '-A2'
}
def __init__(self,
image_in="",
image_t2="",
image_out="",
bet_type="",
fval=0.5,
gval=0,
center_coord=(0, 0, 0),
discard_bet=False,
save_mask=False,
applythresh=False,
save_skull=False,
save_overlay=False,
verbose=False,
suffix="_brain",
prefix=""
):
self._image_in = image_in
self._image_t2 = image_t2
self._image_out = image_out
self._bet_type = bet_type
self._fval = fval
self._gval = gval
self._center_coord = center_coord
self._discard_bet = discard_bet
self._save_mask = save_mask
self._applythresh = applythresh
self._save_skull = save_skull
self._save_overlay = save_overlay
self._verbose = verbose
self._suffix = suffix
self._prefix = prefix
self._bool_argmap = {
'-o': self._save_overlay,
'-m': self._save_mask,
'-s': self._save_skull,
'-n': self._discard_bet,
'-t': self._applythresh
}
# the input image string
@property
def image_in(self):
return self._image_in
@image_in.setter
def image_in(self, val):
assert isinstance(val, str), "image_in must be a string"
self._image_in = val
# the optional T2w input image str
@property
def image_t2(self):
return self._image_t2
@image_t2.setter
def image_t2(self, val):
assert isinstance(val, str), "image_t2 must be a string"
self._image_t2 = val
# the output image string
@property
def image_out(self):
return self._image_out
@image_out.setter
def image_out(self, val):
assert isinstance(val, str), "image_out must be a string"
self._image_out = val
@property
def bet_type(self):
return self._bet_type
@bet_type.setter
def bet_type(self, val):
assert isinstance(val, str), "bet type must be a string"
self._bet_type = val
@property
def fval(self):
return self._fval
@fval.setter
def fval(self, val):
val = float(val)
assert (val >= 0) & (val <= 1), "fval must be in the range 0 .. 1"
self._fval = val
@property
def gval(self):
return self._gval
@gval.setter
def gval(self, val):
val = float(val)
assert (val >= -1) & (val <= 1), "gval must be in the range -1 .. 1"
self._gval = val
@property
def center_coord(self):
return self._center_coord
@center_coord.setter
def center_coord(self, coord):
assert (isinstance(coord, tuple)) & (len(coord) == 3)
self._center_coord = coord
@property
def discard_bet(self):
return self._discard_bet
@discard_bet.setter
def discard_bet(self, val):
assert isinstance(val, bool), "discard_bet must be a bool"
self._bool_argmap['-n'] = val
self._discard_bet = val
@property
def save_mask(self):
return self._save_mask
@save_mask.setter
def save_mask(self, val):
assert isinstance(val, bool), "save_mask must be a bool"
self._bool_argmap['-m'] = val
self._save_mask = val
@property
def applythresh(self):
return self._applythresh
@applythresh.setter
def applythresh(self, val):
assert isinstance(val, bool), "applythresh must be a bool"
self._bool_argmap['-t'] = val
self._applythresh = val
@property
def save_skull(self):
return self._save_skull
@save_skull.setter
def save_skull(self, val):
assert isinstance(val, bool), "save_skull must be a bool"
self._bool_argmap['-s'] = val
self._save_skull = val
@property
def save_overlay(self):
return self._save_overlay
@save_overlay.setter
def save_overlay(self, val):
assert isinstance(val, bool), "save_overlay must be a bool"
self._bool_argmap['-o'] = val
self._save_overlay = val
@property
def verbose(self):
return self._verbose
@verbose.setter
def verbose(self, val):
assert isinstance(val, bool), "verbose must be a bool"
self._verbose = val
@property
def suffix(self):
return self._suffix
@suffix.setter
def suffix(self, val):
assert isinstance(val, str), "suffix must be a string"
self._suffix = val
@property
def prefix(self):
return self._prefix
@prefix.setter
def prefix(self, val):
assert isinstance(val, str), "prefix must be a string"
self._prefix = val
def run(self, cb=None):
"""
:return:
dictionary
{
bet_input: str,
bet_output: str,
bet_mask: str,
bet_skull: str,
bet_overlay: str
}
"""
idle.run(self._run, onFinish=cb)
def _run(self):
# submit(" ".join(self.command()))
subprocess.run(self.command())
def command(self):
"""
make command line string to call program
"""
FSLDIR = os.getenv("FSLDIR", None)
if FSLDIR is None:
return False
if not os.path.isfile(self.image_in):
return False
if (len(self.image_t2) > 0) & (os.path.isfile(self.image_t2) is False):
return False
cmd = [
os.path.join(FSLDIR, 'bin', 'bet'),
self.image_in,
self.image_out,
'-f', str(self.fval),
'-g', str(self.gval)
]
if self._center_coord != (0, 0, 0):
(x, y, z) = self._center_coord
cmd.extend(['-c', str(x), str(y), str(z)])
for key in self._bool_argmap:
if self._bool_argmap[key]:
cmd.append(key)
if self.bet_type != "":
if self.bet_type == "-A2":
cmd.append(self.bet_type)
cmd.append(self.image_t2)
else:
cmd.append(self.bet_type)
print(" ".join(cmd))
return cmd
class Flirt(object):
flirt_type_choices = [
"input to reference",
"low res to high res to reference"
]
search_img_choices = [
"not aligned but same orientation",
"already virtually aligned (no search)",
"not aligned and different orientation"
]
cost_func_choices = [
"corratio",
"mutualinfo",
"normcorr",
"normmi",
"leastsq",
"labeldiff",
"bbr"
]
interp_choices = [
"trilinear",
"nearestneighbour",
"sinc",
"spline"
]
def __init__(self,
in_img="",
ref_img="",
in_lowres="",
dof_in_to_ref=12,
dof_lowres_to_highres=12,
ref_weight_img="",
in_weight_img="",
in_lowres_weight_img="",
secondary_img_list=[],
cost="",
bins=256,
interp="trilinear",
search_xmin=-90,
search_xmax=90,
search_ymin=-90,
search_ymax=90,
search_zmin=-90,
search_zmax=90
):
pass
---
# the pnm view layout specification
appName: BET
windowSize:
width: 800
height: 500
layout:
- notebook:
- page_Inputs:
- group_Files:
- column:
- filepath: {label: Input file, propName: inputFile}
- filepath: {label: Output file, propName: outputFile}
- row:
- number: {label: F value, propName: fval, showLimits: 0}
- column:
- FsleyesImage: {name: FsleyesImage}
- page_Options:
- column:
- choice: {label: BET run type, propName: betRunType}
\ No newline at end of file
#!/usr/bin/env python
"""
views are the graphical layouts of windows.
User interaction is controlled by guis.py.
Data is stored and updated using tools.py
Author: Taylor Hanayik, hanayik@gmail.com
"""
from os.path import dirname, join, abspath
import wx
import wx.lib.scrolledpanel as scrolled
from fsleyes_widgets.floatslider import SliderSpinPanel
import fsl.gui.widgets as fslwidgets
class BetOptions(wx.CollapsiblePane):
"""
BetOptions is a collapsible pane containing widgets that control
bet's operation.
add the Options pane to a parent's sizer with a proportion value of 0.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
pane = self.GetPane()
sizer = wx.BoxSizer(wx.VERTICAL)
# the dropdown choices for the bet mode
self.bet_choice_panel = wx.Panel(pane)
self.bet_choice_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.bet_choice_label = wx.StaticText(self.bet_choice_panel, label="BET mode")
self.choice_btype = wx.Choice(self.bet_choice_panel, choices=[])
self.choice_btype.SetSelection(0)
self.bet_choice_sizer.Add(self.bet_choice_label, 0, wx.ALL, 5)
self.bet_choice_sizer.Add(self.choice_btype, 0, wx.ALL, 5)
self.bet_choice_panel.SetSizer(self.bet_choice_sizer)
# the checkboxes for configuring bet
self.cb_save_bet = wx.CheckBox(pane, label="Save brain-extracted image")
self.cb_save_bet.SetValue(True) # default to always saving the Betted image
self.cb_save_mask = wx.CheckBox(pane, label="Save brain mask image")
self.cb_apply_thr = wx.CheckBox(pane, label="Apply thresholding to brain and mask image")
self.cb_save_skull = wx.CheckBox(pane, label="Save exterior skull surface image")
self.cb_save_overlay = wx.CheckBox(pane, label="Save brain overlay image")
self.cb_verbose = wx.CheckBox(pane, label="Verbose")
self.cb_verbose.Hide()
# the fractional intensity slider (contained in a panel with a label)
self.fval_panel = wx.Panel(pane)
self.fval_panel.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.fval_control = SliderSpinPanel(self.fval_panel, value=0.5, minValue=0, maxValue=1, style=0)
self.fval_label = wx.StaticText(self.fval_panel, label="Fractional intensity")
self.fval_panel.sizer.Add(self.fval_label, 0, wx.ALL, 5)
self.fval_panel.sizer.Add(self.fval_control, 0, wx.ALL, 5)
self.fval_panel.SetSizer(self.fval_panel.sizer)
# the gradient intensity slider
self.gval_panel = wx.Panel(pane)
self.gval_panel.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.gval_control = SliderSpinPanel(self.gval_panel, value=0, minValue=-1, maxValue=1, style=16)
self.gval_label = wx.StaticText(self.gval_panel, label="Gradient intensity")
self.gval_panel.sizer.Add(self.gval_label, 0, wx.ALL, 5)
self.gval_panel.sizer.Add(self.gval_control, 0, wx.ALL, 5)
self.gval_panel.SetSizer(self.gval_panel.sizer)
# the bet center coordinates
self.coord_panel = wx.Panel(pane)
self.coord_panel.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.coordx = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.coordy = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.coordz = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.label_coordstr = wx.StaticText(self.coord_panel, label="Center point: ")
self.labelx = wx.StaticText(self.coord_panel, label="X ")
self.labely = wx.StaticText(self.coord_panel, label="Y ")
self.labelz = wx.StaticText(self.coord_panel, label="Z ")
self.coord_panel.sizer.Add(self.label_coordstr, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labelx, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordx, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labely, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordy, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labelz, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordz, 0, wx.ALL, 5)
self.coord_panel.SetSizer(self.coord_panel.sizer)
# now add all of the options widgets to the sizer
sizer.Add(self.fval_panel, 0, wx.ALL, 0) # 0 pixel border since the fval_panel already applied a 5 pix border
sizer.Add(self.bet_choice_panel, 0, wx.ALL, 0)
sizer.Add(self.cb_save_bet, 0, wx.ALL, 5)
sizer.Add(self.cb_save_mask, 0, wx.ALL, 5)
sizer.Add(self.cb_apply_thr, 0, wx.ALL, 5)
sizer.Add(self.cb_save_skull, 0, wx.ALL, 5)
sizer.Add(self.cb_save_overlay, 0, wx.ALL, 5)
sizer.Add(self.cb_verbose, 0, wx.ALL, 5)
sizer.Add(self.gval_panel, 0, wx.ALL, 0)
sizer.Add(self.coord_panel, 0, wx.ALL, 0)
# now layout the widgets so they can be sized appropriately (automatically done by wx)
pane.SetSizer(sizer)
class FlirtOptions(wx.CollapsiblePane):
"""
FlirtOptions is a collapsible pane containing widgets that control
flirt's operation.
add the Options pane to a parent's sizer with a proportion value of 0.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
pane = self.GetPane()
sizer = wx.BoxSizer(wx.VERTICAL)
# the dropdown choices for the bet mode
self.search_panel = wx.Panel(pane)
search_sizer = wx.BoxSizer(wx.VERTICAL)
self.search_ch_panel = wx.Panel(self.search_panel)
search_ch_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.search_choice_label = wx.StaticText(self.search_panel, label="Search config")
self.choice_stype = wx.Choice(self.search_panel, choices=[])
self.choice_stype.SetSelection(0)
search_ch_sizer.Add(self.search_choice_label, 0, wx.ALL, 5)
search_ch_sizer.Add(self.choice_stype, 0, wx.ALL, 5)
self.search_ch_panel.SetSizer(search_ch_sizer)
search_sizer.Add(self.search_ch_panel, 0, wx.ALL, 5)
self.search_panel.SetSizer(search_sizer)
# the bet center coordinates
self.coord_panel = wx.Panel(pane)
self.coord_panel.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.coordx = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.coordy = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.coordz = wx.SpinCtrlDouble(self.coord_panel, min=0, max=10000, initial=0, inc=1)
self.label_coordstr = wx.StaticText(self.coord_panel, label="Center point: ")
self.labelx = wx.StaticText(self.coord_panel, label="X ")
self.labely = wx.StaticText(self.coord_panel, label="Y ")
self.labelz = wx.StaticText(self.coord_panel, label="Z ")
self.coord_panel.sizer.Add(self.label_coordstr, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labelx, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordx, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labely, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordy, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.labelz, 0, wx.ALL, 5)
self.coord_panel.sizer.Add(self.coordz, 0, wx.ALL, 5)
self.coord_panel.SetSizer(self.coord_panel.sizer)
# now add all of the options widgets to the sizer
sizer.Add(self.fval_panel, 0, wx.ALL, 0) # 0 pixel border since the fval_panel already applied a 5 pix border
sizer.Add(self.bet_choice_panel, 0, wx.ALL, 0)
sizer.Add(self.cb_save_bet, 0, wx.ALL, 5)
sizer.Add(self.cb_save_mask, 0, wx.ALL, 5)
sizer.Add(self.cb_apply_thr, 0, wx.ALL, 5)
sizer.Add(self.cb_save_skull, 0, wx.ALL, 5)
sizer.Add(self.cb_save_overlay, 0, wx.ALL, 5)
sizer.Add(self.cb_verbose, 0, wx.ALL, 5)
sizer.Add(self.gval_panel, 0, wx.ALL, 0)
sizer.Add(self.coord_panel, 0, wx.ALL, 0)
# now layout the widgets so they can be sized appropriately (automatically done by wx)
pane.SetSizer(sizer)
class BetView(wx.Panel):
"""
Bet view defines the graphical layout of widgets for using BET
"""
def __init__(self, parent, title="BET", **kwargs):
super().__init__(parent, **kwargs)
self.parent = parent
self.title = title
sizer = wx.BoxSizer(wx.VERTICAL)
self.title_panel = fslwidgets.Title(self, self.title)
sizer.Add(self.title_panel, proportion=0, flag=wx.ALIGN_CENTER | wx.ALL, border=5)
self.input = fslwidgets.Input(self).set_label("Input image*")
sizer.Add(self.input, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
self.t2_input = fslwidgets.Input(self).set_label("Additional T2w image")
sizer.Add(self.t2_input, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
self.t2_input.Hide() # hide by default unless a special bet mode is chosen
self.output = fslwidgets.Output(self).set_label("Output Image*")
sizer.Add(self.output, proportion=0, flag=wx.EXPAND | wx.ALL, border=5)
self.action_panel = fslwidgets.ToolActionPanel(self)
self.action_panel.pause_icon.Hide() # hide the pause icon since it is not needed
sizer.Add(self.action_panel, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
self._scroll_panel = scrolled.ScrolledPanel(self)
scroll_sizer = wx.BoxSizer(wx.VERTICAL)
self.options = BetOptions(self._scroll_panel, label="Options", style=wx.CP_NO_TLW_RESIZE)
scroll_sizer.Add(self.options, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=10)
self.orthoview = fslwidgets.OrthoView(self._scroll_panel, label="Image Display", style=wx.CP_NO_TLW_RESIZE)
scroll_sizer.Add(self.orthoview, proportion=0, flag=wx.EXPAND | wx.ALL, border=10)