Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
FSL
fslpy
Commits
5917cf19
Commit
5917cf19
authored
Nov 12, 2021
by
Paul McCarthy
🚵
Browse files
Merge branch 'rel/3.7.1' into 'v3.7'
Rel/3.7.1 See merge request fsl/fslpy!314
parents
33999995
7a054c5b
Pipeline
#11474
passed with stages
in 5 minutes and 16 seconds
Changes
10
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
5917cf19
...
@@ -171,6 +171,12 @@ test:3.9:
...
@@ -171,6 +171,12 @@ test:3.9:
<<
:
*test_template
<<
:
*test_template
# test:3.10:
# stage: test
# image: pauldmccarthy/fsleyes-py310-wxpy4-gtk3
# <<: *test_template
test:build-pypi-dist:
test:build-pypi-dist:
stage
:
test
stage
:
test
image
:
pauldmccarthy/fsleyes-py37-wxpy4-gtk3
image
:
pauldmccarthy/fsleyes-py37-wxpy4-gtk3
...
...
CHANGELOG.rst
View file @
5917cf19
...
@@ -2,6 +2,26 @@ This document contains the ``fslpy`` release history in reverse chronological
...
@@ -2,6 +2,26 @@ This document contains the ``fslpy`` release history in reverse chronological
order.
order.
3.7.1 (Friday 12th November 2021)
---------------------------------
Changed
^^^^^^^
* BIDS and ``dcm2niix`` ``.json`` sidecar files with control characters
are now accepted (!312).
Fixed
^^^^^
* Fixed an issue with temporary input files created by :mod:`fsl.wrappers`
functions not being deleted (!313).
3.7.0 (Friday 20th August 2021)
3.7.0 (Friday 20th August 2021)
-------------------------------
-------------------------------
...
@@ -11,7 +31,7 @@ Added
...
@@ -11,7 +31,7 @@ Added
* New :mod:`fsl.wrappers.fsl_sub` wrapper function for the ``fsl_sub``
* New :mod:`fsl.wrappers.fsl_sub` wrapper function for the ``fsl_sub``
command.
command
(!309)
.
Changed
Changed
...
@@ -20,19 +40,19 @@ Changed
...
@@ -20,19 +40,19 @@ Changed
* Performance of the :mod:`.imglob`, :mod:`.imln`, :mod:`imtest`, :mod:`.imrm`
* Performance of the :mod:`.imglob`, :mod:`.imln`, :mod:`imtest`, :mod:`.imrm`
and :mod:`.remove_ext` scripts has been improved, by re-organising them to
and :mod:`.remove_ext` scripts has been improved, by re-organising them to
avoid unnecessary and expensive imports such as ``numpy``.
avoid unnecessary and expensive imports such as ``numpy``
(!310)
.
* The default behaviour of the :func:`fsl.utils.run.run` function (and hence
* The default behaviour of the :func:`fsl.utils.run.run` function (and hence
that of all :mod:`fsl.wrappers` functions) has been changed so that the
that of all :mod:`fsl.wrappers` functions) has been changed so that the
standard output and error of the called command is now forwarded to the
standard output and error of the called command is now forwarded to the
calling Python process, in addition to being returned from ``run`` as
calling Python process, in addition to being returned from ``run`` as
strings. In other words, the default behaviour of ``run('cmd')``, is now
strings. In other words, the default behaviour of ``run('cmd')``, is now
equivalent to ``run('cmd', log={"tee":True})``. The previous default
equivalent to ``run('cmd', log={"tee":True})``. The previous default
behaviour can be achieved with ``run('cmd', log={"tee":False})``.
behaviour can be achieved with ``run('cmd', log={"tee":False})``
(!309)
.
* The :func:`fsl.utils.run.run` and :func:`fsl.utils.run.runfsl` functions
* The :func:`fsl.utils.run.run` and :func:`fsl.utils.run.runfsl` functions
(and hence all :mod:`fsl.wrappers` functions) have been modified to use
(and hence all :mod:`fsl.wrappers` functions) have been modified to use
``fsl.wrappers.fsl_sub`` instead of ``fsl.utils.fslsub.submit``. This is an
``fsl.wrappers.fsl_sub`` instead of ``fsl.utils.fslsub.submit``. This is an
internal change which should not affect the usage of the ``run``, ``runfsl``
internal change which should not affect the usage of the ``run``, ``runfsl``
or wrapper functions.
or wrapper functions
(!309)
.
Deprecated
Deprecated
...
@@ -41,10 +61,10 @@ Deprecated
...
@@ -41,10 +61,10 @@ Deprecated
* :class:`fsl.utils.fslsub.SubmitParams` and :func:`fsl.utils.fslsub.submit`
* :class:`fsl.utils.fslsub.SubmitParams` and :func:`fsl.utils.fslsub.submit`
have been deprecated in favour of using the ``fsl.wrappers.fsl_sub`` wrapper
have been deprecated in favour of using the ``fsl.wrappers.fsl_sub`` wrapper
function.
function
(!309)
.
* The :func:`fsl.utils.fslsub.info` function has been deprecated in favour of
* The :func:`fsl.utils.fslsub.info` function has been deprecated in favour of
using the ``fsl_sub.report`` function, from the separate `fsl_sub
using the ``fsl_sub.report`` function, from the separate `fsl_sub
<https://git.fmrib.ox.ac.uk/fsl/fsl_sub>`_ Python library.
<https://git.fmrib.ox.ac.uk/fsl/fsl_sub>`_ Python library
(!309)
.
3.6.4 (Tuesday 3rd August 2021)
3.6.4 (Tuesday 3rd August 2021)
...
...
README.rst
View file @
5917cf19
...
@@ -19,7 +19,7 @@ programming library written in Python. It is used by `FSLeyes
...
@@ -19,7 +19,7 @@ programming library written in Python. It is used by `FSLeyes
<https://git.fmrib.ox.ac.uk/fsl/fsleyes/fsleyes/>`_.
<https://git.fmrib.ox.ac.uk/fsl/fsleyes/fsleyes/>`_.
``fslpy`` is tested against Python versions 3.7, 3.8 and 3.
9
.
``fslpy`` is tested against Python versions 3.7, 3.8
, 3.9,
and 3.
10
.
Installation
Installation
...
...
fsl/data/image.py
View file @
5917cf19
...
@@ -1569,7 +1569,7 @@ def loadMetadata(image):
...
@@ -1569,7 +1569,7 @@ def loadMetadata(image):
jsonfile
=
op
.
join
(
dirname
,
'{}.json'
.
format
(
basename
))
jsonfile
=
op
.
join
(
dirname
,
'{}.json'
.
format
(
basename
))
if
op
.
exists
(
jsonfile
):
if
op
.
exists
(
jsonfile
):
with
open
(
jsonfile
,
'rt'
)
as
f
:
with
open
(
jsonfile
,
'rt'
)
as
f
:
return
json
.
load
(
f
)
return
json
.
load
(
f
,
strict
=
False
)
return
{}
return
{}
...
...
fsl/utils/bids.py
View file @
5917cf19
...
@@ -187,7 +187,7 @@ def isBIDSFile(filename, strict=True):
...
@@ -187,7 +187,7 @@ def isBIDSFile(filename, strict=True):
def
loadMetadataFile
(
filename
):
def
loadMetadataFile
(
filename
):
"""Load ``filename`` (assumed to be JSON), returning its contents. """
"""Load ``filename`` (assumed to be JSON), returning its contents. """
with
open
(
filename
,
'rt'
)
as
f
:
with
open
(
filename
,
'rt'
)
as
f
:
return
json
.
load
(
f
)
return
json
.
load
(
f
,
strict
=
False
)
def
loadMetadata
(
filename
):
def
loadMetadata
(
filename
):
...
...
fsl/version.py
View file @
5917cf19
...
@@ -47,7 +47,7 @@ import re
...
@@ -47,7 +47,7 @@ import re
import
string
import
string
__version__
=
'3.7.
0
'
__version__
=
'3.7.
1
'
"""Current version number, as a string. """
"""Current version number, as a string. """
...
...
fsl/wrappers/wrapperutils.py
View file @
5917cf19
...
@@ -1046,9 +1046,16 @@ def fileOrImage(*args, **kwargs):
...
@@ -1046,9 +1046,16 @@ def fileOrImage(*args, **kwargs):
# in-memory image - we have
# in-memory image - we have
# to save it out to a file
# to save it out to a file
if
infile
is
None
:
if
infile
is
None
or
not
op
.
exists
(
infile
):
hd
,
infile
=
tempfile
.
mkstemp
(
fslimage
.
defaultExt
())
hd
,
infile
=
tempfile
.
mkstemp
(
fslimage
.
defaultExt
(),
dir
=
workdir
)
os
.
close
(
hd
)
os
.
close
(
hd
)
# Create a copy of the input image and
# save that, so the original doesn't
# get associated with the temp file
val
=
nib
.
nifti1
.
Nifti1Image
(
np
.
asanyarray
(
val
.
dataobj
),
None
,
val
.
header
)
val
.
to_filename
(
infile
)
val
.
to_filename
(
infile
)
return
infile
return
infile
...
@@ -1110,7 +1117,7 @@ def fileOrArray(*args, **kwargs):
...
@@ -1110,7 +1117,7 @@ def fileOrArray(*args, **kwargs):
infile
=
None
infile
=
None
if
isinstance
(
val
,
np
.
ndarray
):
if
isinstance
(
val
,
np
.
ndarray
):
hd
,
infile
=
tempfile
.
mkstemp
(
'.txt'
)
hd
,
infile
=
tempfile
.
mkstemp
(
'.txt'
,
dir
=
workdir
)
os
.
close
(
hd
)
os
.
close
(
hd
)
np
.
savetxt
(
infile
,
val
,
fmt
=
'%0.18f'
)
np
.
savetxt
(
infile
,
val
,
fmt
=
'%0.18f'
)
...
@@ -1176,6 +1183,7 @@ def fileOrText(*args, **kwargs):
...
@@ -1176,6 +1183,7 @@ def fileOrText(*args, **kwargs):
if
not
isinstance
(
val
,
pathlib
.
Path
):
if
not
isinstance
(
val
,
pathlib
.
Path
):
with
tempfile
.
NamedTemporaryFile
(
mode
=
'w'
,
with
tempfile
.
NamedTemporaryFile
(
mode
=
'w'
,
suffix
=
'.txt'
,
suffix
=
'.txt'
,
dir
=
workdir
,
delete
=
False
)
as
f
:
delete
=
False
)
as
f
:
f
.
write
(
val
)
f
.
write
(
val
)
infile
=
f
.
name
infile
=
f
.
name
...
...
tests/test_bids.py
View file @
5917cf19
...
@@ -110,6 +110,21 @@ def test_loadMetadata():
...
@@ -110,6 +110,21 @@ def test_loadMetadata():
assert
fslbids
.
loadMetadata
(
t1
)
==
{
**
meta4
,
**
meta2
,
**
meta1
}
assert
fslbids
.
loadMetadata
(
t1
)
==
{
**
meta4
,
**
meta2
,
**
meta1
}
def
test_loadMetadata_control_characters
():
dd
=
Path
(
'dataset_description.json'
)
t1
=
Path
(
'sub-01/func/sub-01_task-stim_bold.nii.gz'
)
json1
=
Path
(
'sub-01/func/sub-01_task-stim_bold.json'
)
meta1
=
{
"a"
:
"1"
,
"b"
:
"2
\x19\x20
"
}
smeta1
=
'{"a" : "1", "b" : "2
\x19\x20
"}'
with
tempdir
():
dd
.
touch
()
Path
(
op
.
dirname
(
t1
)).
mkdir
(
parents
=
True
)
t1
.
touch
()
assert
fslbids
.
loadMetadata
(
t1
)
==
{}
json1
.
write_text
(
smeta1
)
assert
fslbids
.
loadMetadata
(
t1
)
==
meta1
def
test_loadMetadata_symlinked
():
def
test_loadMetadata_symlinked
():
ddreal
=
Path
(
'a'
)
ddreal
=
Path
(
'a'
)
...
...
tests/test_image.py
View file @
5917cf19
...
@@ -1484,6 +1484,21 @@ def test_loadMeta_badJSON():
...
@@ -1484,6 +1484,21 @@ def test_loadMeta_badJSON():
assert
list
(
img
.
metaKeys
())
==
[]
assert
list
(
img
.
metaKeys
())
==
[]
def
test_loadMeta_control_characters
():
with
tempdir
():
make_image
(
'image.nii.gz'
)
with
open
(
'image.json'
,
'wt'
)
as
f
:
f
.
write
(
'{"a" : 1, "b" : "abc
\x19\x1b
"}'
)
# bad json should not cause failure
img
=
fslimage
.
Image
(
'image.nii.gz'
,
loadMeta
=
True
)
assert
list
(
img
.
metaKeys
())
==
[
'a'
,
'b'
]
assert
img
.
getMeta
(
'a'
)
==
1
assert
img
.
getMeta
(
'b'
)
==
'abc
\x19\x1b
'
def
test_loadMetadata
():
def
test_loadMetadata
():
with
tempdir
():
with
tempdir
():
make_image
(
'image.nii.gz'
)
make_image
(
'image.nii.gz'
)
...
...
tests/test_wrappers/test_wrapperutils.py
View file @
5917cf19
...
@@ -876,3 +876,61 @@ def test_cmdwrapper_cmdonly_assert():
...
@@ -876,3 +876,61 @@ def test_cmdwrapper_cmdonly_assert():
assert
func
()[
0
].
strip
()
==
'hello'
assert
func
()[
0
].
strip
()
==
'hello'
os
.
remove
(
'file'
)
os
.
remove
(
'file'
)
assert
func
(
cmdonly
=
True
)
==
[
'echo'
,
'hello'
]
assert
func
(
cmdonly
=
True
)
==
[
'echo'
,
'hello'
]
def
test_fileOrArray_all_tempfiles_cleared
():
tempfiles
=
[]
@
wutils
.
fileOrArray
(
'in_'
,
'out'
)
def
array
(
in_
,
out
):
tempfiles
.
extend
((
in_
,
out
))
i
=
np
.
loadtxt
(
in_
)
i
=
i
+
1
np
.
savetxt
(
out
,
i
)
arr
=
np
.
array
([[
1
,
2
],
[
3
,
4
]])
arrout
=
array
(
arr
,
wutils
.
LOAD
).
out
assert
np
.
all
(
np
.
isclose
(
arrout
,
arr
+
1
))
assert
len
(
tempfiles
)
==
2
assert
not
any
(
op
.
exists
(
f
)
for
f
in
tempfiles
)
def
test_fileOrImage_all_tempfiles_cleared
():
tempfiles
=
[]
@
wutils
.
fileOrImage
(
'in_'
,
'out'
)
def
image
(
in_
,
out
):
tempfiles
.
extend
((
in_
,
out
))
i
=
nib
.
load
(
in_
)
i
=
nib
.
Nifti1Image
(
i
.
get_fdata
()
+
1
,
np
.
eye
(
4
))
i
.
to_filename
(
out
)
arr
=
np
.
array
([[
1
,
2
],
[
3
,
4
]])
img
=
nib
.
nifti1
.
Nifti1Image
(
arr
,
np
.
eye
(
4
))
imgout
=
image
(
img
,
wutils
.
LOAD
).
out
assert
np
.
all
(
np
.
isclose
(
imgout
.
get_fdata
(),
img
.
get_fdata
()
+
1
))
assert
len
(
tempfiles
)
==
2
assert
not
any
(
op
.
exists
(
f
)
for
f
in
tempfiles
)
def
test_fileOrText_all_tempfiles_cleared
():
tempfiles
=
[]
@
wutils
.
fileOrText
(
'in_'
,
'out'
)
def
text
(
in_
,
out
):
tempfiles
.
extend
((
in_
,
out
))
with
open
(
in_
,
'rt'
)
as
inf
,
open
(
out
,
'wt'
)
as
outf
:
outf
.
write
(
inf
.
read
())
outf
.
write
(
'456'
)
txt
=
'123'
txtout
=
text
(
txt
,
wutils
.
LOAD
).
out
assert
txtout
==
'123456'
assert
len
(
tempfiles
)
==
2
assert
not
any
(
op
.
exists
(
f
)
for
f
in
tempfiles
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment