Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
fslpy
Manage
Activity
Members
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Analyze
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Evan Edmond
fslpy
Commits
f011b82f
Commit
f011b82f
authored
7 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
further experimentation
parent
0634907a
No related branches found
No related tags found
No related merge requests found
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
fsl/wrappers/__init__.py
+28
-22
28 additions, 22 deletions
fsl/wrappers/__init__.py
fsl/wrappers/bet.py
+4
-1
4 additions, 1 deletion
fsl/wrappers/bet.py
fsl/wrappers/flirt.py
+38
-52
38 additions, 52 deletions
fsl/wrappers/flirt.py
fsl/wrappers/wrapperutils.py
+365
-101
365 additions, 101 deletions
fsl/wrappers/wrapperutils.py
with
435 additions
and
176 deletions
fsl/wrappers/__init__.py
+
28
−
22
View file @
f011b82f
...
@@ -8,25 +8,31 @@
...
@@ -8,25 +8,31 @@
them to be called from Python.
them to be called from Python.
"""
"""
from
.wrapperutils
import
(
applyArgStyle
,
# noqa
from
.bet
import
(
bet
,)
# noqa
required
,
from
.eddy
import
(
eddy_cuda
,
# noqa
fileOrImage
,
topup
)
fileOrArray
,
from
.flirt
import
(
flirt
,
# noqa
RETURN
,
invxfm
,
SHOW_IF_TRUE
,
applyxfm
,
HIDE_IF_TRUE
)
concatxfm
,
from
.bet
import
(
bet
,)
# noqa
mcflirt
)
from
.eddy
import
(
eddy_cuda
,
# noqa
from
.fnirt
import
(
fnirt
,
# noqa
topup
)
applywarp
,
from
.flirt
import
(
flirt
,
# noqa
invwarp
,
invxfm
,
convertwarp
)
applyxfm
,
from
.fslmaths
import
(
fslmaths
,)
# noqa
concatxfm
,
from
.fugue
import
(
fugue
,
# noqa
mcflirt
)
sigloss
)
from
.fnirt
import
(
fnirt
,
# noqa
from
.melodic
import
(
melodic
,
# noqa
applywarp
,
fsl_regfilt
)
invwarp
,
from
.misc
import
(
fslreorient2std
,
# noqa
convertwarp
)
fslroi
,
from
.fslmaths
import
(
fslmaths
,)
# noqa
slicer
,
from
.fugue
import
(
fugue
,
# noqa
cluster
)
sigloss
)
from
.melodic
import
(
melodic
,
# noqa
fsl_regfilt
)
from
.misc
import
(
fslreorient2std
,
# noqa
fslroi
,
slicer
,
cluster
)
This diff is collapsed.
Click to expand it.
fsl/wrappers/bet.py
+
4
−
1
View file @
f011b82f
...
@@ -11,6 +11,10 @@ import fsl.utils.run as run
...
@@ -11,6 +11,10 @@ import fsl.utils.run as run
from
.
import
wrapperutils
as
wutils
from
.
import
wrapperutils
as
wutils
def
pybet
():
# ??
pass
@wutils.fileOrImage
(
'
input
'
,
'
output
'
)
@wutils.fileOrImage
(
'
input
'
,
'
output
'
)
def
bet
(
input
,
output
,
**
kwargs
):
def
bet
(
input
,
output
,
**
kwargs
):
"""
Delete non-brain tissue from an image of the whole head.
"""
Delete non-brain tissue from an image of the whole head.
...
@@ -20,7 +24,6 @@ def bet(input, output, **kwargs):
...
@@ -20,7 +24,6 @@ def bet(input, output, **kwargs):
:arg mask:
:arg mask:
:arg robust:
:arg robust:
:arg fracintensity:
:arg fracintensity:
:arg seg:
Refer to the ``bet`` command-line help for details on all arguments.
Refer to the ``bet`` command-line help for details on all arguments.
"""
"""
...
...
This diff is collapsed.
Click to expand it.
fsl/wrappers/flirt.py
+
38
−
52
View file @
f011b82f
...
@@ -20,60 +20,34 @@
...
@@ -20,60 +20,34 @@
import
fsl.utils.run
as
run
import
fsl.utils.run
as
run
import
fsl.utils.assertions
as
asrt
import
fsl.utils.assertions
as
asrt
import
fsl.data.image
as
fslimage
import
fsl.data.image
as
fslimage
from
.
import
wrapperutils
as
wutils
def
flirt
(
src
,
ref
,
out
=
None
,
omat
=
None
,
dof
=
None
,
cost
=
None
,
wmseg
=
None
,
@wutils.required
(
'
src
'
,
'
ref
'
)
init
=
None
,
schedule
=
None
,
echospacing
=
None
,
pedir
=
None
,
@wutils.fileOrImage
(
'
src
'
,
'
ref
'
,
'
out
'
,
'
wmseg
'
,
'
fieldmap
'
,
'
fieldmapmask
'
)
fieldmap
=
None
,
fieldmapmask
=
None
,
bbrslope
=
None
,
bbrtype
=
None
,
@wutils.fileOrArray
(
'
init
'
,
'
omat
'
,
'
wmcoords
'
,
'
wmnorms
'
)
interp
=
None
,
refweight
=
None
,
applyisoxfm
=
None
,
usesqform
=
False
,
def
flirt
(
src
,
ref
,
**
kwargs
):
nosearch
=
False
,
verbose
=
0
):
"""
FLIRT (FMRIB
'
s Linear Image Registration Tool).
"""
"""
FLIRT (FMRIB
'
s Linear Image Registration Tool).
"""
asrt
.
assertIsNifti
(
src
,
ref
)
asrt
.
assertIsNifti
(
src
,
ref
)
asrt
.
assertFileExists
(
src
,
ref
)
cmd
=
"
flirt -in {0} -ref {1}
"
.
format
(
src
,
ref
)
valmap
=
{
'
usesqform
'
:
wutils
.
SHOW_IF_TRUE
,
if
out
is
not
None
:
'
displayinit
'
:
wutils
.
SHOW_IF_TRUE
,
asrt
.
assertIsNifti
(
out
)
'
noresample
'
:
wutils
.
SHOW_IF_TRUE
,
cmd
+=
"
-out {0}
"
.
format
(
out
)
'
forcescaling
'
:
wutils
.
SHOW_IF_TRUE
,
if
omat
is
not
None
:
'
applyxfm
'
:
wutils
.
SHOW_IF_TRUE
,
cmd
+=
"
-omat {0}
"
.
format
(
omat
)
'
nosearch
'
:
wutils
.
SHOW_IF_TRUE
,
if
dof
is
not
None
:
'
noclamp
'
:
wutils
.
SHOW_IF_TRUE
,
cmd
+=
"
-dof {0}
"
.
format
(
dof
)
'
noresampblur
'
:
wutils
.
SHOW_IF_TRUE
,
if
cost
is
not
None
:
'
2D
'
:
wutils
.
SHOW_IF_TRUE
,
cmd
+=
"
-cost {0}
"
.
format
(
cost
)
'
v
'
:
wutils
.
SHOW_IF_TRUE
,
if
wmseg
is
not
None
:
'
version
'
:
wutils
.
SHOW_IF_TRUE
,
asrt
.
assertIsNifti
(
wmseg
)
'
help
'
:
wutils
.
SHOW_IF_TRUE
,
cmd
+=
"
-wmseg {0}
"
.
format
(
wmseg
)
}
if
init
is
not
None
:
cmd
+=
"
-init {0}
"
.
format
(
init
)
cmd
=
[
'
flirt
'
,
'
-in
'
,
src
,
'
-ref
'
,
ref
]
if
schedule
is
not
None
:
cmd
+=
wutils
.
applyArgStyle
(
'
-
'
,
valmap
=
valmap
,
**
kwargs
)
cmd
+=
"
-schedule {0}
"
.
format
(
schedule
)
if
echospacing
is
not
None
:
cmd
+=
"
-echospacing {0}
"
.
format
(
echospacing
)
if
pedir
is
not
None
:
cmd
+=
"
-pedir {0}
"
.
format
(
pedir
)
if
fieldmap
is
not
None
:
cmd
+=
"
-fieldmap {0}
"
.
format
(
fieldmap
)
if
fieldmapmask
is
not
None
:
cmd
+=
"
-fieldmapmask {0}
"
.
format
(
fieldmapmask
)
if
bbrslope
is
not
None
:
cmd
+=
"
-bbrslope {0}
"
.
format
(
bbrslope
)
if
bbrtype
is
not
None
:
cmd
+=
"
-bbrtype {0}
"
.
format
(
bbrtype
)
if
interp
is
not
None
:
cmd
+=
"
-interp {0}
"
.
format
(
interp
)
if
refweight
is
not
None
:
asrt
.
assertIsNifti
(
refweight
)
cmd
+=
"
-refweight {0}
"
.
format
(
refweight
)
if
applyisoxfm
is
not
None
:
cmd
+=
"
-applyisoxfm {0}
"
.
format
(
applyisoxfm
)
if
verbose
is
not
None
:
cmd
+=
"
-verbose {0}
"
.
format
(
verbose
)
if
usesqform
:
cmd
+=
"
-usesqform
"
if
nosearch
:
cmd
+=
"
-nosearch
"
return
run
.
runfsl
(
cmd
)
return
run
.
runfsl
(
cmd
)
...
@@ -94,13 +68,25 @@ def applyxfm(src, ref, mat, out, interp='spline'):
...
@@ -94,13 +68,25 @@ def applyxfm(src, ref, mat, out, interp='spline'):
cmd
=
"
flirt -init {0} -in {1} -ref {2} -applyxfm -out {3} -interp {4}
"
cmd
=
"
flirt -init {0} -in {1} -ref {2} -applyxfm -out {3} -interp {4}
"
return
run
.
runfsl
(
cmd
.
format
(
mat
,
src
,
ref
,
out
,
interp
))
return
run
.
runfsl
(
cmd
.
format
(
mat
,
src
,
ref
,
out
,
interp
))
@wutils.required
(
'
inmat1
'
,
'
inmat2
'
,
'
outmat
'
)
@wutils.fileOrArray
(
'
inmat1
'
,
'
inmat2
'
,
'
outmat
'
)
def
concatxfm
(
inmat1
,
inmat2
,
outmat
):
def
concatxfm
(
inmat1
,
inmat2
,
outmat
):
"""
Tool to concatenate two FSL transformation matrices.
"""
"""
Tool to concatenate two FSL transformation matrices.
"""
print
(
'
inmat1
'
,
inmat1
)
print
(
'
inmat2
'
,
inmat2
)
print
(
'
outmat
'
,
outmat
)
asrt
.
assertFileExists
(
inmat1
,
inmat2
)
asrt
.
assertFileExists
(
inmat1
,
inmat2
)
cmd
=
"
convert_xfm -omat {0} -concat {1} {2}
"
cmd
=
[
'
convert_xfm
'
,
return
run
.
runfsl
(
cmd
.
format
(
outmat
,
inmat2
,
inmat1
))
'
-omat
'
,
outmat
,
'
-concat
'
,
inmat2
,
inmat1
]
return
run
.
runfsl
(
cmd
)
def
mcflirt
(
infile
,
outfile
,
reffile
=
None
,
spline_final
=
True
,
plots
=
True
,
def
mcflirt
(
infile
,
outfile
,
reffile
=
None
,
spline_final
=
True
,
plots
=
True
,
...
...
This diff is collapsed.
Click to expand it.
fsl/wrappers/wrapperutils.py
+
365
−
101
View file @
f011b82f
#!/usr/bin/env python
#!/usr/bin/env python
#
#
# wrapperutils.py -
# wrapperutils.py - Functions and decorators used by the FSL wrapper
# functions.
#
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
#
"""
This module contains functions and decorators used by the FSL wrapper
functions.
.. autosummary::
:nosignatures:
applyArgStyle
required
fileOrImage
fileOrArray
"""
import
os.path
as
op
import
os.path
as
op
import
os
import
os
import
sys
import
inspect
import
inspect
import
tempfile
import
tempfile
import
warnings
import
warnings
...
@@ -16,50 +29,133 @@ import collections
...
@@ -16,50 +29,133 @@ import collections
import
six
import
six
import
nibabel
as
nib
import
nibabel
as
nib
import
numpy
as
np
import
fsl.utils.tempdir
as
tempdir
import
fsl.utils.tempdir
as
tempdir
import
fsl.data.image
as
fslimage
import
fsl.data.image
as
fslimage
class
_BooleanFlag
(
object
):
def
_update_wrapper
(
wrapper
,
wrapped
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
show
):
"""
Replacement for the built-in ``functools.update_wrapper``. This
self
.
show
=
show
implementation ensures that the wrapper function has an attribute
def
__eq__
(
self
,
other
):
called ``__wrapped__``, which refers to the ``wrapped`` function.
return
type
(
other
)
==
type
(
self
)
and
self
.
show
==
other
.
show
This behaviour is only required in Python versions < 3.4.
"""
wrapper
=
functools
.
update_wrapper
(
wrapper
,
wrapped
,
*
args
,
**
kwargs
)
# Python >= 3.4 does things right
if
sys
.
version_info
[
0
]
*
10
+
sys
.
version_info
[
1
]
<
3.4
:
wrapper
.
__wrapped__
=
wrapped
return
wrapper
SHOW_IF_TRUE
=
_BooleanFlag
(
True
)
def
_unwrap
(
func
):
HIDE_IF_TRUE
=
_BooleanFlag
(
False
)
"""
Replacement for the built-in ``inspect.unwrap`` function, which
is not present in Python versions prior to 3.4.
"""
# Python >= 3.4 has an inspect.unwrap function
if
sys
.
version_info
[
0
]
*
10
+
sys
.
version_info
[
1
]
<
3.4
:
return
inspect
.
unwrap
(
func
)
# Otherwise we follow the __wrapped__ chain ourselves
if
hasattr
(
func
,
'
__wrapped__
'
):
return
_unwrap
(
func
.
__wrapped__
)
return
func
SHOW_IF_TRUE
=
object
()
"""
Constant to be used in the ``valmap`` passed to the :func:`applyArgStyle`
function.
When a ``SHOW_IF_TRUE`` argument is ``True``, it is added to the generated
command line arguments.
"""
HIDE_IF_TRUE
=
object
()
"""
Constant to be used in the ``valmap`` passed to the :func:`applyArgStyle`
function.
When a ``HIDE_IF_TRUE`` argument is ``True``, it is suppressed from the
generated command line arguments.
"""
def
applyArgStyle
(
style
,
argmap
=
None
,
valmap
=
None
,
**
kwargs
):
def
applyArgStyle
(
style
,
argmap
=
None
,
valmap
=
None
,
**
kwargs
):
"""
Turns the given ``kwargs`` into command line options. This function
is intended to be used to automatically generate command line options
from arguments passed into a Python function.
:arg style: Controls how the ``kwargs`` are converted into command-line
options - must be one of the following:
- `
'
-
'
`: ``-name val``
- `
'
--
'
`: ``--name val``
- `
'
-=
'
`: ``-name=val``
- `
'
--=
'
`: ``--name=val``
:arg argmap: Dictionary of ``{kwarg-name : cli-name}`` mappings. This can
be used if you want to use different argument names in your
Python function for the command-line options.
:arg valmap: Dictionary of ``{cli-name : value}`` mappings. This can be
used to define specific semantics for some command-line
options. Acceptable values for ``value`` are as follows
- :data:`SHOW_IF_TRUE` - if the argument is present, and
``True`` in ``kwargs``, the command line option
will be added (without any arguments).
- :data:`HIDE_IF_TRUE` - if the argument is present, and
``False`` in ``kwargs``, the command line option
will be added (without any arguments).
- Any other constant value. If the argument is present
in ``kwargs``, its command-line option will be
added, with the constant value as its argument.
The argument for any options not specified in the ``valmap``
will be converted into strings.
def
fmtarg
(
arg
,
style
):
:arg kwargs: Arguments to be converted into command-line options.
:returns: A list containing the generated command-line options.
"""
if
style
not
in
(
'
-
'
,
'
--
'
,
'
-=
'
,
'
--=
'
):
raise
ValueError
(
'
Invalid style: {}
'
.
format
(
style
))
if
argmap
is
None
:
argmap
=
{}
if
valmap
is
None
:
valmap
=
{}
def
fmtarg
(
arg
):
if
style
in
(
'
-
'
,
'
-=
'
):
arg
=
'
-{}
'
.
format
(
arg
)
if
style
in
(
'
-
'
,
'
-=
'
):
arg
=
'
-{}
'
.
format
(
arg
)
elif
style
in
(
'
--
'
,
'
--=
'
):
arg
=
'
--{}
'
.
format
(
arg
)
elif
style
in
(
'
--
'
,
'
--=
'
):
arg
=
'
--{}
'
.
format
(
arg
)
return
arg
return
arg
def
fmtval
(
val
,
style
=
None
):
def
fmtval
(
val
):
if
isinstance
(
val
,
collections
.
Sequence
)
and
\
if
isinstance
(
val
,
collections
.
Sequence
)
and
\
not
isinstance
(
val
,
six
.
string_types
):
not
isinstance
(
val
,
six
.
string_types
):
return
'
'
.
join
([
str
(
v
)
for
v
in
val
])
return
'
'
.
join
([
str
(
v
)
for
v
in
val
])
else
:
else
:
return
str
(
val
)
return
str
(
val
)
if
style
not
in
(
'
-
'
,
'
--
'
,
'
-=
'
,
'
--=
'
):
raise
ValueError
(
'
Invalid style: {}
'
.
format
(
style
))
args
=
[]
args
=
[]
for
k
,
v
in
kwargs
.
items
():
for
k
,
v
in
kwargs
.
items
():
k
=
argmap
.
get
(
k
,
k
)
k
=
argmap
.
get
(
k
,
k
)
mapv
=
valmap
.
get
(
k
,
fmtval
(
v
,
style
))
mapv
=
valmap
.
get
(
k
,
fmtval
(
v
))
k
=
fmtarg
(
k
,
style
)
k
=
fmtarg
(
k
)
if
(
mapv
is
SHOW_IF_TRUE
and
v
)
or
\
(
mapv
is
HIDE_IF_TRUE
and
not
v
):
args
.
append
(
k
)
if
mapv
in
(
SHOW_IF_TRUE
,
HIDE_IF_TRUE
):
if
v
==
mapv
.
show
:
args
.
append
(
k
)
elif
'
=
'
in
style
:
elif
'
=
'
in
style
:
args
.
append
(
'
{}={}
'
.
format
(
k
,
mapv
))
args
.
append
(
'
{}={}
'
.
format
(
k
,
mapv
))
else
:
else
:
...
@@ -72,110 +168,216 @@ def required(*reqargs):
...
@@ -72,110 +168,216 @@ def required(*reqargs):
"""
Decorator which makes sure that all specified keyword arguments are
"""
Decorator which makes sure that all specified keyword arguments are
present before calling the decorated function.
present before calling the decorated function.
"""
"""
def
decorator
(
func
):
def
decorator
(
func
):
def
wrapper
(
**
kwargs
):
def
wrapper
(
*
args
,
**
kwargs
):
kwargs
=
kwargs
.
copy
()
kwargs
.
update
(
argsToKwargs
(
func
,
args
))
for
reqarg
in
reqargs
:
for
reqarg
in
reqargs
:
assert
reqarg
in
kwargs
assert
reqarg
in
kwargs
return
func
(
**
kwargs
)
return
func
(
**
kwargs
)
return
wrapper
return
_update_wrapper
(
wrapper
,
func
)
return
decorator
return
decorator
def
argsToKwargs
(
func
,
args
):
def
argsToKwargs
(
func
,
args
):
"""
Given a function, and a sequence of positional arguments destined
"""
Given a function, and a sequence of positional arguments destined
for that function, converts the positional arguments into a dict
for that function, converts the positional arguments into a dict
of keyword arguments. Used by the :class:`_FileOr
Image
` class.
of keyword arguments. Used by the :class:`_FileOr
Thing
` class.
"""
"""
# getfullargspec is the only way to get the names
# of positional arguments in Python 2.x. It is
func
=
_unwrap
(
func
)
# deprecated in python 3.5, but not in python 3.6.
with
warnings
.
catch_warnings
():
# getargspec is the only way to get the names
warnings
.
filterwarnings
(
'
ignore
'
,
category
=
DeprecationWarning
)
# of positional arguments in Python 2.x.
spec
=
inspect
.
getfullargspec
(
func
)
if
sys
.
version_info
[
0
]
<
3
:
argnames
=
inspect
.
getargspec
(
func
).
args
# getargspec is deprecated in python 3.x
else
:
# getfullargspec is deprecated in
# python 3.5, but not in python 3.6.
with
warnings
.
catch_warnings
():
warnings
.
filterwarnings
(
'
ignore
'
,
category
=
DeprecationWarning
)
argnames
=
inspect
.
getfullargspec
(
func
).
args
kwargs
=
collections
.
OrderedDict
()
kwargs
=
collections
.
OrderedDict
()
for
name
,
val
in
zip
(
spec
.
arg
s
,
args
):
for
name
,
val
in
zip
(
argname
s
,
args
):
kwargs
[
name
]
=
val
kwargs
[
name
]
=
val
return
kwargs
return
kwargs
RETURN
=
object
()
RETURN
=
object
()
"""
"""
Constant used by the :class:`_FileOrThing` class to indicate that an output
file should be loaded into memory and returned as a Python object.
"""
"""
class
_FileOrImage
(
object
):
class
_FileOrThing
(
object
):
"""
"""
Decorator which ensures that certain arguments which are passed into the
decorated function are always passed as file names. Both positional and
keyword arguments can be specified.
The ``_FileOrThing`` class is not intended to be used directly - see the
:func:`fileOrImage` and :func:`fileOrArray` decorator functions for more
details.
These decorators are intended for functions which wrap a command-line tool,
i.e. where some inputs/outputs need to be specified as file names.
**Inputs**
Any arguments which are not of type ``Thing`` are passed through to the
decorated function unmodified. Arguments which are of type ``Thing`` are
saved to a temporary file, and the name of that file is passed to the
function.
Inputs:
**Outputs**
- In-memory nibabel images loaded from a file. The image is replaced with
its file name.
- In-memory nibabel images. The image is saved to a temporary file, and
replaced with the temporary file
'
s name. The file is deleted after the
function has returned.
Outputs:
If an argument is given the special :data:`RETURN` value, it is assumed
- File name: The file name is passed straight through to the function.
to be an output argument. In this case, it is replaced with a temporary
- ``RETURN``: A temporary file name is passed to the function. After the
file name then, after the function has completed, that file is loaded
function has completed, the image is loaded into memory and the
into memory, and the value returned (along with the function
'
s output,
temporary file is deleted. The image is returned from the function
and any other arguments with a value of ``RETURN``).
call.
**Return value**
Functions decorated with a ``_FileOrThing`` decorator will always return a
tuple, where the first element is the function
'
s actual return value. The
remainder of the tuple will contain any arguments that were given the
special ``RETURN`` value. ``None`` is returned for any ``RETURN``
arguments corresponded to output files that were not generated by the
function.
**Example**
As an example of using the ``fileOrArray`` decorator on a function
which concatenates two files containing affine transformations, and
saves the output to a file::
# if atob, btoc, or output are passed
# in as arrays, they are converted to
# file names.
@fileOrArray(
'
atob
'
,
'
btoc
'
,
'
output
'
)
def concat(atob, btoc, output=None):
# inputs are guaranteed to be files
atob = np.loadtxt(atob)
btoc = np.loadtxt(atoc)
atoc = np.dot(btoc, atob)
if output is not None:
np.savetxt(output, atoc)
Because we have decorated the ``concat`` function with :func:`fileToArray`,
it can be called with either file names, or Numpy arrays::
# All arguments are passed through
# unmodified - the output will be
# saved to a file called atoc.mat
concat(
'
atob.txt
'
,
'
btoc.txt
'
,
'
atoc.mat
'
)
# The output is returned as a numpy
# array (in a tuple with the concat
# function
'
s return value)
atoc = concat(
'
atob.txt
'
,
'
btoc.txt
'
, RETURN)[1]
# The inputs are saved to temporary
# files, and those file names are
# passed to the concat function.
atoc = concat(np.diag([2, 2, 2, 0]), np.diag([3, 3, 3, 3]), RETURN)[1]
"""
"""
def
__init__
(
self
,
*
imgargs
):
def
__init__
(
self
,
prepareThing
,
loadThing
,
*
things
):
"""
"""
Initialise a ``_FileOrThing`` decorator.
:arg prepareThing: Function which
:arg loadThing: Function which is called for arguments that
were set to :data:`RETURN`.
:arg things:
"""
"""
self
.
__imgargs
=
imgargs
self
.
__prepareThing
=
prepareThing
self
.
__loadThing
=
loadThing
self
.
__things
=
things
def
__call__
(
self
,
func
):
def
__call__
(
self
,
func
):
"""
"""
Creates and returns the real decorator function.
"""
"""
return
functools
.
partial
(
self
.
__wrapper
,
func
)
self
.
__func
=
func
self
.
__isFileOrThing
=
False
if
hasattr
(
func
,
'
__self__
'
):
self
.
__isFileOrThing
=
isinstance
(
func
.
__self__
,
_FileOrThing
)
wrapper
=
functools
.
partial
(
self
.
__wrapper
,
func
)
return
_update_wrapper
(
wrapper
,
func
)
def
__wrapper
(
self
,
func
,
*
args
,
**
kwargs
):
def
__wrapper
(
self
,
func
,
*
args
,
**
kwargs
):
"""
"""
Function which wraps ``func``, ensuring that any arguments of
type ``Thing`` are saved to temporary files, and any arguments
with the value :data:`RETURN` are loaded and returned.
"""
"""
func
=
self
.
__func
isFileOrThing
=
self
.
__isFileOrThing
kwargs
=
kwargs
.
copy
()
kwargs
.
update
(
argsToKwargs
(
func
,
args
))
kwargs
.
update
(
argsToKwargs
(
func
,
args
))
# Create a tempdir to store any temporary
# Create a tempdir to store any temporary
# input/output
image
s, but don't change
# input/output
thing
s, but don't change
# into it, as file paths passed to the
# into it, as file paths passed to the
# function may be relative.
# function may be relative.
with
tempdir
.
tempdir
(
changeto
=
False
)
as
td
:
with
tempdir
.
tempdir
(
changeto
=
False
)
as
td
:
kwargs
,
infiles
,
outfiles
=
self
.
__prepare
Ar
gs
(
td
,
kwargs
)
kwargs
,
infiles
,
outfiles
=
self
.
__prepare
Thin
gs
(
td
,
kwargs
)
# Call the function
# Call the function
result
=
func
(
**
kwargs
)
result
=
func
(
**
kwargs
)
# Load the output
image
s that
# Load the output
thing
s that
# were specified as RETURN
# were specified as RETURN
out
im
gs
=
[]
out
thin
gs
=
[]
for
of
in
outfiles
:
for
of
in
outfiles
:
# output file didn't get created
# output file didn't get created
if
not
op
.
exists
(
of
):
if
not
op
.
exists
(
of
):
o
i
=
None
o
t
=
None
# load the file, and create
# load the thing
# an in-memory copy (the file
# is going to get deleted)
else
:
else
:
oi
=
nib
.
load
(
of
)
ot
=
self
.
__loadThing
(
of
)
oi
=
nib
.
nifti1
.
Nifti1Image
(
oi
.
get_data
(),
None
,
oi
.
header
)
out
im
gs
.
append
(
o
i
)
out
thin
gs
.
append
(
o
t
)
return
tuple
([
result
]
+
outimgs
)
if
isFileOrThing
:
things
=
result
[
1
:]
result
=
result
[
0
]
return
tuple
([
result
]
+
things
+
outthings
)
else
:
return
tuple
([
result
]
+
outthings
)
def
__prepare
Ar
gs
(
self
,
workdir
,
kwargs
):
def
__prepare
Thin
gs
(
self
,
workdir
,
kwargs
):
"""
"""
"""
"""
...
@@ -183,48 +385,110 @@ class _FileOrImage(object):
...
@@ -183,48 +385,110 @@ class _FileOrImage(object):
infiles
=
[]
infiles
=
[]
outfiles
=
[]
outfiles
=
[]
for
imgarg
in
self
.
__
imgar
gs
:
for
tname
in
self
.
__
thin
gs
:
img
=
kwargs
.
get
(
imgarg
,
None
)
tval
=
kwargs
.
get
(
tname
,
None
)
# Not specified, nothing to do
if
tval
is
None
:
if
img
is
None
:
continue
continue
# This is an input image which has
tval
,
infile
,
outfile
=
self
.
__prepareThing
(
workdir
,
tname
,
tval
)
# been specified as an in-memory
# nibabel image. if the image has
if
infile
is
not
None
:
infiles
.
append
(
infile
)
# a backing file, replace the image
if
outfile
is
not
None
:
outfiles
.
append
(
outfile
)
# object with the file name.
# Otherwise, save the image out to
kwargs
[
tname
]
=
tval
# a temporary file, and replace the
# image with the file name.
if
isinstance
(
img
,
nib
.
nifti1
.
Nifti1Image
):
imgfile
=
img
.
get_filename
()
# in-memory image - we have
# to save it out to a file
if
imgfile
is
None
:
hd
,
imgfile
=
tempfile
.
mkstemp
(
fslimage
.
defaultExt
())
os
.
close
(
hd
)
img
.
to_filename
(
imgfile
)
infiles
.
append
(
imgfile
)
# replace the image with its
# file name
kwargs
[
img
]
=
imgfile
# This is an output image, and the
# caller has requested that it be
# returned from the function call
# as an in-memory image.
if
img
==
RETURN
:
kwargs
[
imgarg
]
=
'
{}.nii.gz
'
.
format
(
imgarg
)
outfiles
.
append
(
imgarg
)
return
kwargs
,
infiles
,
outfiles
return
kwargs
,
infiles
,
outfiles
fileOrImage
=
_FileOrImage
def
fileOrImage
(
*
imgargs
):
"""
Decorator which can be used to ensure that any NIfTI images are saved
to file, and output images can be loaded and returned as ``nibabel``
image objects.
"""
def
prepareArg
(
workdir
,
name
,
val
):
newval
=
val
infile
=
None
outfile
=
None
# This is an input image which has
# been specified as an in-memory
# nibabel image. if the image has
# a backing file, replace the image
# object with the file name.
# Otherwise, save the image out to
# a temporary file, and replace the
# image with the file name.
if
isinstance
(
val
,
nib
.
nifti1
.
Nifti1Image
):
imgfile
=
val
.
get_filename
()
# in-memory image - we have
# to save it out to a file
if
imgfile
is
None
:
hd
,
imgfile
=
tempfile
.
mkstemp
(
fslimage
.
defaultExt
())
os
.
close
(
hd
)
val
.
to_filename
(
imgfile
)
infile
=
imgfile
# replace the image with its
# file name
newval
=
imgfile
# This is an output image, and the
# caller has requested that it be
# returned from the function call
# as an in-memory image.
elif
val
==
RETURN
:
newval
=
op
.
join
(
workdir
,
'
{}.nii.gz
'
.
format
(
name
))
outfile
=
newval
return
newval
,
infile
,
outfile
def
loadImage
(
path
):
# create an independent in-memory
# copy of the image file
img
=
nib
.
load
(
path
)
return
nib
.
nifti1
.
Nifti1Image
(
img
.
get_data
(),
None
,
img
.
header
)
return
_FileOrThing
(
prepareArg
,
loadImage
,
*
imgargs
)
def
fileOrArray
(
*
arrargs
):
"""
Decorator which can be used to ensure that any Numpy arrays are saved
to text files, and output files can be loaded and returned as Numpy arrays.
"""
def
prepareArg
(
workdir
,
name
,
val
):
newval
=
val
infile
=
None
outfile
=
None
# Input has been provided as a numpy
# array - save it to a file, and
# replace the argument with the file
# name
if
isinstance
(
val
,
np
.
ndarray
):
hd
,
arrfile
=
tempfile
.
mkstemp
(
'
.txt
'
)
os
.
close
(
hd
)
np
.
savetxt
(
arrfile
,
val
,
fmt
=
'
%0.18f
'
)
newval
=
arrfile
# This is an output, and the caller has
# requested that it be returned from the
# function call as an in-memory array.
elif
val
==
RETURN
:
newval
=
op
.
join
(
workdir
,
'
{}.txt
'
.
format
(
name
))
outfile
=
newval
return
newval
,
infile
,
outfile
return
_FileOrThing
(
prepareArg
,
np
.
loadtxt
,
*
arrargs
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment