Skip to content

Commit

Permalink
Merge branch 'master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
FSL User committed Aug 14, 2017
2 parents 349e406 + d049748 commit 172ab4e
Show file tree
Hide file tree
Showing 13 changed files with 1,584 additions and 1,255 deletions.
13 changes: 13 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
BasedOnStyle: WebKit
AccessModifierOffset: -4
AlignTrailingComments: true
BreakBeforeBraces: Allman
ColumnLimit: 0
IndentWidth: 4
KeepEmptyLinesAtTheStartOfBlocks: false
PointerBindsToType: false
SpacesBeforeTrailingComments: 1
TabWidth: 4
UseTab: Never
Standard: Cpp03

4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ configure_file(asl_reg.in asl_reg @ONLY)
configure_file(quasil.in quasil @ONLY)

INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/oxford_asl
${CMAKE_CURRENT_BINARY_DIR}/asl_calib
${CMAKE_CURRENT_BINARY_DIR}/asl_calib
${CMAKE_CURRENT_BINARY_DIR}/asl_reg
${CMAKE_CURRENT_BINARY_DIR}/quasil
${CMAKE_CURRENT_BINARY_DIR}/asl_file
asl_gui
DESTINATION bin)

INSTALL(FILES asl/fslhelpers.py asl/gui.py asl/__init__.py DESTINATION python/asl)
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ PROJNAME = oxford_asl
USRINCFLAGS = -I${INC_NEWMAT} -I${INC_ZLIB}
USRLDFLAGS = -L${LIB_NEWMAT} -L${LIB_ZLIB}


LIBS = -lutils -lnewimage -lmiscmaths -lm -lnewmat -lfslio -lniftiio -lznz -lz

XFILES = asl_file
SCRIPTS = oxford_asl asl_calib asl_reg quasil
SCRIPTS = oxford_asl asl_calib asl_reg quasil asl_gui
PYMODULES = asl/fslhelpers.py asl/gui.py asl/__init__.py
RUNTCLS = Asl
VERSIONED = oxford_asl asl_calib asl_reg quasil

OBJS = readoptions.o asl_functions.o

Expand All @@ -27,11 +28,16 @@ all: ${XFILES} ${SCRIPTS}
asl_file: ${OBJS} asl_file.o
${CXX} ${CXXFLAGS} ${LDFLAGS} -o $@ ${OBJS} asl_file.o ${LIBS}

$(SCRIPTS): %: %.in FORCE
$(VERSIONED): %: %.in FORCE
sed -e "s/@GIT_SHA1@/${GIT_SHA1}/" -e "s/@GIT_DATE@/${GIT_DATE}/" $< >$@

postinstallscript: $(PYMODULES)
mkdir -p $(FSLDEVDIR)/python/asl ; \
cp $(PYMODULES) $(FSLDEVDIR)/python/asl/ ; \
cd ..

clean:
rm ${SCRIPTS}
rm -f ${VERSIONED} asl_file *.o

FORCE:

2 changes: 2 additions & 0 deletions asl/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pkg-util style namespace package to allow asl package to be split over multiple locations
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
131 changes: 131 additions & 0 deletions asl/fslhelpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env python
#
# FSL helper functions - named fslhelpers so as not to clash with 'official' FSL python
# modules

import os, sys
import glob
import shutil
import shlex
import subprocess
import math
import errno

import nibabel as nib
import numpy as np

# Where to look for 'local' programs - default to dir of calling program
# This enables users to override standard FSL programs by putting their
# own copies in the same directory as the script they are calling
LOCAL_DIR = os.path.dirname(os.path.abspath(sys.argv[0]))
#print("FSLHELPERS: using local binaries dir: %s" % LOCAL_DIR)

def set_localdir(localdir):
global LOCAL_DIR
LOCAL_DIR = localdir

class Prog:
def __init__(self, cmd, localdir=""):
self.cmd = cmd

def _find(self):
"""
Find the program, either in the 'local' directory, or in $FSLDEVDIR/bin or $FSLDIR/bin
This is called each time the program is run so the caller can control where programs
are searched for at any time
"""
if "FSLDIR" in os.environ:
fsldir = os.environ["FSLDIR"]
else:
fsldir = LOCAL_DIR
if "FSLDEVDIR" in os.environ:
fsldevdir = os.environ["FSLDEVDIR"]
else:
fsldevdir = LOCAL_DIR

local_path = os.path.join(LOCAL_DIR, self.cmd)
if os.path.isfile(local_path) and os.access(local_path, os.X_OK):
return local_path
elif os.path.exists(os.path.join(fsldevdir, "bin/%s" % self.cmd)):
return os.path.join(fsldevdir, "bin/%s" % self.cmd)
elif os.path.exists(os.path.join(fsldir, "bin/%s" % self.cmd)):
return os.path.join(fsldir, "bin/%s" % self.cmd)
else:
return self.cmd

def run(self, args):
""" Run, writing output to stdout and returning retcode """
cmd = self._find()
cmd_args = shlex.split(cmd + " " + args)
out = ""
#print(" ".join(cmd_args))
p = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while 1:
retcode = p.poll() #returns None while subprocess is running
line = p.stdout.readline()
out += line
if retcode is not None: break
if retcode != 0:
raise RuntimeError(out)
else:
return out

class Image:
def __init__(self, fname, file_type="Image"):
if fname is None or fname == "":
raise RuntimeError("%s file not specified" % file_type)

self.file_type = file_type
self.base = fname.split(".", 1)[0]

# Try to figure out the extension
exts = ["", ".nii", ".nii.gz"]
matches = []
for ext in exts:
if os.path.exists("%s%s" % (self.base, ext)):
matches.append(ext)

if len(matches) == 0:
raise RuntimeError("%s file %s not found" % (file_type, fname))
elif len(matches) > 1:
raise RuntimeError("%s file %s is ambiguous" % (file_type, fname))

self.ext = matches[0]
self.full = os.path.abspath("%s%s" % (self.base, ext))
self.nii = nib.load(self.full)
self.shape = self.nii.shape

def data(self):
return self.nii.get_data()

def new_nifti(self, data=None):
""" Return new Nifti oject, taking header info from this image """
if data is None: data=self.data()
nii = nib.Nifti1Image(data, self.nii.header.get_best_affine())
nii.update_header()
return nii

def check_shape(self, shape=None):
if len(self.shape) != len(shape):
raise RuntimeError("%s: expected %i dims, got %i" % (self.file_type, len(shape), len(self.shape)))
if self.shape != shape:
raise RuntimeError("%s: shape (%s) does not match (%s)" % (self.file_type, str(self.shape), str(shape)))

maths = Prog("fslmaths")
roi = Prog("fslroi")
stats = Prog("fslstats")
merge = Prog("fslmerge")
bet = Prog("bet")
flirt = Prog("flirt")
fast = Prog("fast")

def imcp(src, dest):
Prog("imcp").run("%s %s" % (src, dest))

def mkdir(dir, fail_if_exists=False, warn_if_exists=True):
try:
os.makedirs(dir)
except OSError as e:
if e.errno == errno.EEXIST:
if fail_if_exists: raise
elif warn_if_exists: print("WARNING: mkdir - Directory %s already exists" % dir)
28 changes: 20 additions & 8 deletions asl.py → asl/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def __init__(self, parent):
self.nslices = 1
self.view = 0
self.figure = Figure(figsize=(3.5, 3.5), dpi=100, facecolor='black')
self.axes = self.figure.add_subplot(111, axisbg='black')
self.axes = self.figure.add_subplot(111, facecolor='black')
self.axes.get_xaxis().set_ticklabels([])
self.axes.get_yaxis().set_ticklabels([])
self.canvas = FigureCanvas(self, -1, self.figure)
Expand Down Expand Up @@ -379,7 +379,7 @@ def update(self, evt=None):
self.run_label.SetForegroundColour(wx.Colour(0, 128, 0))
self.run_label.SetLabel("Ready to Go")
self.run_btn.Enable(True)
except Exception, e:
except Exception as e:
self.run_btn.Enable(False)
self.run_label.SetForegroundColour(wx.Colour(255, 0, 0))
self.run_label.SetLabel(str(e))
Expand All @@ -392,6 +392,11 @@ def get_preview_data(self):
"""
Run ASL_FILE for perfusion weighted image - just for the preview
"""
infile = self.input.data()
if infile == "":
# Don't bother if we have not input file yet!
return None

tempdir = tempfile.mkdtemp()
self.preview_data = None
try:
Expand Down Expand Up @@ -442,7 +447,7 @@ def get_run_sequence(self):
N = self.input.ntis()
if self.input.tc_pairs(): N *= 2
if nvols % N != 0:
self.input.nrepeats_label.SetLabel("<Unknown>")
self.input.nrepeats_label.SetLabel("Unknown - Number of PLDs inconsistent with number of volumes")
raise RuntimeError("Input data contains %i volumes - not consistent with %i TIs and TC pairs=%s" % (img.shape[3], self.input.ntis(), self.input.tc_pairs()))
else:
self.input.nrepeats_label.SetLabel("%i" % (nvols / N))
Expand Down Expand Up @@ -885,7 +890,8 @@ def __init__(self, parent):
self.bolus_dur_ch.Bind(wx.EVT_CHOICE, self.update)
self.bolus_dur_num = NumberChooser(self, min=0, max=2.5, step=0.1, initial=1.8)
self.bolus_dur_num.span = 2
self.bolus_dur_num.spin.Bind(wx.EVT_SPINCTRLDOUBLE, self.bolus_dur_changed)
#self.bolus_dur_num.spin.Bind(wx.EVT_SPINCTRLDOUBLE, self.bolus_dur_changed)
self.bolus_dur_num.spin.Bind(wx.EVT_SPINCTRL, self.bolus_dur_changed)
self.bolus_dur_num.slider.Bind(wx.EVT_SLIDER, self.bolus_dur_changed)
self.pack("Bolus duration (s)", self.bolus_dur_ch, self.bolus_dur_num)

Expand Down Expand Up @@ -1062,6 +1068,8 @@ def __init__(self, parent, label=None, min=0, max=1, initial=0.5, step=0.1, digi
self.label = wx.StaticText(self, label=label)
self.hbox.Add(self.label, proportion=0, flag=wx.ALIGN_CENTRE_VERTICAL)
# Set a very large maximum as we want to let the user override the default range
#self.spin = wx.SpinCtrl(self, min=0, max=100000, initial=initial)
#self.spin.Bind(wx.EVT_SPINCTRL, self.spin_changed)
self.spin = wx.SpinCtrlDouble(self, min=0, max=100000, inc=step, initial=initial)
self.spin.SetDigits(digits)
self.spin.Bind(wx.EVT_SPINCTRLDOUBLE, self.spin_changed)
Expand Down Expand Up @@ -1121,7 +1129,7 @@ def __init__(self, parent, n, default=1.8):
def GetValues(self):
try:
return [float(self.GetCellValue(0, c)) for c in range(self.n)]
except ValueError, e:
except ValueError as e:
raise RuntimeError("Non-numeric values in number list")

def set_size(self, n):
Expand Down Expand Up @@ -1188,12 +1196,12 @@ def on_paint(self, event):
dc.SetBrush(wx.TRANSPARENT_BRUSH)
rect = wx.Rect(leg_start, 20, leg_width/4, 20)
dc.GradientFillLinear(rect, self.get_col(0, True), self.get_col(1.0, True), wx.EAST)
dc.DrawRectangleRect(rect)
dc.DrawRectangle(*rect.Get())
dc.DrawText(self.tis_name, leg_start+leg_width/3, 20)

rect = wx.Rect(leg_start+leg_width, 20, leg_width/4, 20)
dc.GradientFillLinear(rect, self.get_col(0, False), self.get_col(1.0, False), wx.EAST)
dc.DrawRectangleRect(rect)
dc.DrawRectangle(*rect.Get())
dc.DrawText("Repeats", leg_start+4*leg_width/3, 20)

if self.tc_pairs:
Expand Down Expand Up @@ -1323,9 +1331,13 @@ def __init__(self):

self.Layout()

if __name__ == '__main__':
def main():
app = wx.App(redirect=False)
top = AslGui()
top.Show()
app.MainLoop()

if __name__ == '__main__':
main()


Loading

0 comments on commit 172ab4e

Please sign in to comment.