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
aeffabbd
Commit
aeffabbd
authored
8 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
addExt resolves ambiguities a bit better. And also raises custom error type.
parent
abd05f90
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/data/featanalysis.py
+8
-8
8 additions, 8 deletions
fsl/data/featanalysis.py
fsl/data/image.py
+14
-1
14 additions, 1 deletion
fsl/data/image.py
fsl/data/melodicanalysis.py
+3
-3
3 additions, 3 deletions
fsl/data/melodicanalysis.py
fsl/utils/path.py
+127
-15
127 additions, 15 deletions
fsl/utils/path.py
with
152 additions
and
27 deletions
fsl/data/featanalysis.py
+
8
−
8
View file @
aeffabbd
...
...
@@ -90,7 +90,7 @@ def isFEATDir(path):
try
:
fslimage
.
addExt
(
op
.
join
(
path
,
'
filtered_func_data
'
),
mustExist
=
True
)
except
Value
Error
:
except
fslimage
.
Path
Error
:
return
False
if
not
op
.
exists
(
op
.
join
(
dirname
,
'
design.fsf
'
)):
return
False
...
...
@@ -451,7 +451,7 @@ def getDataFile(featdir):
"""
Returns the name of the file in the FEAT directory which contains
the model input data (typically called ``filtered_func_data.nii.gz``).
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
"""
...
...
@@ -464,7 +464,7 @@ def getMelodicFile(featdir):
components (if melodic ICA was performed as part of the FEAT
analysis). This file can be loaded as a :class:`.MelodicImage`.
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
"""
melfile
=
op
.
join
(
featdir
,
'
filtered_func_data.ica
'
,
'
melodic_IC
'
)
return
fslimage
.
addExt
(
melfile
,
mustExist
=
True
)
...
...
@@ -474,7 +474,7 @@ def getResidualFile(featdir):
"""
Returns the name of the file in the FEAT results which contains
the model fit residuals (typically called ``res4d.nii.gz``).
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
"""
...
...
@@ -485,7 +485,7 @@ def getResidualFile(featdir):
def
getPEFile
(
featdir
,
ev
):
"""
Returns the path of the PE file for the specified EV.
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
:arg ev: The EV number (0-indexed).
...
...
@@ -497,7 +497,7 @@ def getPEFile(featdir, ev):
def
getCOPEFile
(
featdir
,
contrast
):
"""
Returns the path of the COPE file for the specified contrast.
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
:arg contrast: The contrast number (0-indexed).
...
...
@@ -509,7 +509,7 @@ def getCOPEFile(featdir, contrast):
def
getZStatFile
(
featdir
,
contrast
):
"""
Returns the path of the Z-statistic file for the specified contrast.
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
:arg contrast: The contrast number (0-indexed).
...
...
@@ -521,7 +521,7 @@ def getZStatFile(featdir, contrast):
def
getClusterMaskFile
(
featdir
,
contrast
):
"""
Returns the path of the cluster mask file for the specified contrast.
Raises a :exc:`
Value
Error` if the file does not exist.
Raises a :exc:`
.Path
Error` if the file does not exist.
:arg featdir: A FEAT directory.
:arg contrast: The contrast number (0-indexed).
...
...
This diff is collapsed.
Click to expand it.
fsl/data/image.py
+
14
−
1
View file @
aeffabbd
...
...
@@ -769,10 +769,22 @@ EXTENSION_DESCRIPTIONS = ['Compressed NIFTI images',
"""
Descriptions for each of the extensions in :data:`ALLOWED_EXTENSIONS`.
"""
REPLACEMENTS
=
{
'
.hdr
'
:
[
'
.img
'
,
'
.img.gz
'
]}
"""
Suffix replacements used by :func:`addExt` to resolve file path
ambiguities - see :func:`fsl.utils.path.addExt`.
"""
DEFAULT_EXTENSION
=
'
.nii.gz
'
"""
The default file extension (TODO read this from ``$FSLOUTPUTTYPE``).
"""
PathError
=
fslpath
.
PathError
"""
Error raised by :mod:`fsl.utils.path` functions when an error occurs.
Made available in this module for convenience.
"""
def
looksLikeImage
(
filename
,
allowedExts
=
None
):
"""
Returns ``True`` if the given file looks like an image, ``False``
otherwise.
...
...
@@ -810,7 +822,8 @@ def addExt(prefix, mustExist=True):
return
fslpath
.
addExt
(
prefix
,
ALLOWED_EXTENSIONS
,
mustExist
,
DEFAULT_EXTENSION
)
DEFAULT_EXTENSION
,
replace
=
REPLACEMENTS
)
def
loadIndexedImageFile
(
filename
):
...
...
This diff is collapsed.
Click to expand it.
fsl/data/melodicanalysis.py
+
3
−
3
View file @
aeffabbd
...
...
@@ -77,7 +77,7 @@ def isMelodicDir(path):
# Must contain an image file called melodic_IC
try
:
fslimage
.
addExt
(
op
.
join
(
dirname
,
'
melodic_IC
'
),
mustExist
=
True
)
except
Value
Error
:
except
fslimage
.
Path
Error
:
return
False
# Must contain files called
...
...
@@ -124,8 +124,8 @@ def getDataFile(meldir):
dataFile
=
op
.
join
(
topDir
,
'
filtered_func_data
'
)
try
:
return
fslimage
.
addExt
(
dataFile
,
mustExist
=
True
)
except
Value
Err
o
r
:
return
None
try
:
return
fslimage
.
addExt
(
dataFile
,
mustExist
=
True
)
except
fslimage
.
Path
Err
p
r
:
return
None
def
getMeanFile
(
meldir
):
...
...
This diff is collapsed.
Click to expand it.
fsl/utils/path.py
+
127
−
15
View file @
aeffabbd
...
...
@@ -15,12 +15,18 @@ paths.
shallowest
addExt
removeExt
getExt
"""
import
os.path
as
op
class
PathError
(
Exception
):
"""
``Exception`` class raised by :func:`addExt` and :func:`getExt`.
"""
pass
def
deepest
(
path
,
suffixes
):
"""
Finds the deepest directory which ends with one of the given
sequence of suffixes, or returns ``None`` if no directories end
...
...
@@ -64,7 +70,11 @@ def shallowest(path, suffixes):
return
None
def
addExt
(
prefix
,
allowedExts
,
mustExist
=
True
,
defaultExt
=
None
):
def
addExt
(
prefix
,
allowedExts
,
mustExist
=
True
,
defaultExt
=
None
,
replace
=
None
):
"""
Adds a file extension to the given file ``prefix``.
If ``mustExist`` is False, and the file does not already have a
...
...
@@ -77,17 +87,47 @@ def addExt(prefix, allowedExts, mustExist=True, defaultExt=None):
extension. A :exc:`ValueError` is raised if:
- No files exist with the given prefix and a supported extension.
- More than one file exists with the given prefix, and a supported
extension.
- ``replace`` is ``None``, and more than one file exists with the
given prefix, and a supported extension.
Otherwise the full file name is returned.
:arg prefix: The file name refix to modify.
:arg mustExist: Whether the file must exist or not.
:arg prefix: The file name
p
refix to modify.
:arg allowedExts: List of allowed file extensions.
:arg mustExist: Whether the file must exist or not.
:arg defaultExt: Default file extension to use.
:arg replace: If multiple files exist with the same ``prefix`` and
supported extensions (e.g. ``file.hdr`` and
``file.img``), this dictionary can be used to resolve
ambiguities. It must have the structure::
{
suffix : [replacement, ...],
...
}
If
files
with
``
suffix
``
and
one
of
the
``
replacement
``
suffixes
exists
,
the
``
suffix
``
file
will
be
ignored
,
and
replaced
with
the
``
replacement
``
file
.
If
multiple
``
replacement
``
files
exist
alongside
the
``
suffix
``
file
,
a
``
PathError
``
is
raised
.
.. note:: The primary use-case of the ``replace`` parameter is to resolve
ambiguity with respect to NIFTI and ANALYSE75 image pairs. By
specifying ``replace={
'
.hdr
'
: [
'
.img
'
.
'
.img.gz
'
}``, the
``addExt`` function is able to figure out what you mean when you
wish to add an extension to ``file``, and ``file.hdr`` and
either ``file.img`` or ``file.img.gz`` (but not both) exist.
"""
if
replace
is
None
:
replace
=
{}
if
not
mustExist
:
# the provided file name already
...
...
@@ -101,31 +141,74 @@ def addExt(prefix, allowedExts, mustExist=True, defaultExt=None):
# If the provided prefix already ends with a
# supported extension , check to see that it exists
if
any
([
prefix
.
endswith
(
ext
)
for
ext
in
allowedExts
]):
extended
=
[
prefix
]
allPaths
=
[
prefix
]
# Otherwise, make a bunch of file names, one per
# supported extension, and test to see if exactly
# one of them exists.
else
:
extended
=
[
prefix
+
ext
for
ext
in
allowedExts
]
allPaths
=
[
prefix
+
ext
for
ext
in
allowedExts
]
exists
=
[
op
.
isfile
(
e
)
for
e
in
extended
]
exists
=
[
op
.
isfile
(
e
)
for
e
in
allPaths
]
nexists
=
sum
(
exists
)
# Could not find any supported file
# with the specified prefix
if
n
ot
any
(
exists
)
:
raise
Value
Error
(
'
Could not find a supported file
with prefix {}
'
.
format
(
prefix
))
if
nexists
==
0
:
raise
Path
Error
(
'
Could not find a supported file
'
'
with prefix {}
'
.
format
(
prefix
))
# Ambiguity! More than one supported
# file with the specified prefix
if
sum
(
exists
)
>
1
:
raise
ValueError
(
'
More than one file with prefix {}
'
.
format
(
prefix
))
# file with the specified prefix.
elif
nexists
>
1
:
# Remove non-existent paths from the
# extended list, get all their
# suffixes, and potential replacements
allPaths
=
[
allPaths
[
i
]
for
i
in
range
(
len
(
allPaths
))
if
exists
[
i
]]
suffixes
=
[
getExt
(
e
,
allowedExts
)
for
e
in
allPaths
]
replacements
=
[
replace
.
get
(
s
)
for
s
in
suffixes
]
hasReplace
=
[
r
is
not
None
for
r
in
replacements
]
for
p
,
r
in
zip
(
allPaths
,
replacements
):
print
'
{} replacements: {}
'
.
format
(
p
,
r
)
# If any replacement has been specified
# for any of the existing suffixes,
# see if we have a unique match for
# exactly one existing suffix, the
# one to be ignored/replaced.
if
sum
(
hasReplace
)
==
1
:
# Make sure there is exactly one potential
# replacement for this suffix. If there's
# more than one (e.g. file.hdr plus both
# file.img and file.img.gz) we can't resolve
# the ambiguity. In this case the code will
# fall through to the raise statement below.
toReplace
=
allPaths
[
hasReplace
.
index
(
True
)]
replacements
=
replacements
[
hasReplace
.
index
(
True
)]
replacements
=
[
prefix
+
ext
for
ext
in
replacements
]
replExists
=
[
r
in
allPaths
for
r
in
replacements
]
if
sum
(
replExists
)
==
1
:
replacedBy
=
replacements
[
replExists
.
index
(
True
)]
allPaths
[
allPaths
.
index
(
toReplace
)]
=
replacedBy
allPaths
=
list
(
set
(
allPaths
))
exists
=
[
True
]
*
len
(
allPaths
)
# There's more than one path match -
# we can't resolve the ambiguity
if
len
(
allPaths
)
>
1
:
raise
PathError
(
'
More than one file with
'
'
prefix {}
'
.
format
(
prefix
))
# Return the full file name of the
# supported file that was found
extIdx
=
exists
.
index
(
True
)
return
extended
[
extIdx
]
return
allPaths
[
extIdx
]
def
removeExt
(
filename
,
allowedExts
):
...
...
@@ -151,3 +234,32 @@ def removeExt(filename, allowedExts):
# and trim it from the file name
return
filename
[:
-
extLen
]
def
getExt
(
filename
,
allowedExts
=
None
):
"""
Returns the extension from the given file name.
If ``allowedExts`` is ``None``, this function is equivalent to using::
os.path.splitext(filename)[1]
If ``allowedExts`` is provided, but the file does not end with an allowed
extension, a :exc:`PathError` is raised.
:arg allowedExts: Allowed/recognised file extensions.
"""
# If allowedExts is not specified,
# we just use op.splitext
if
allowedExts
is
None
:
return
op
.
splitext
(
filename
)[
1
]
# Otherwise, try and find a suffix match
extMatches
=
[
filename
.
endswith
(
ext
)
for
ext
in
allowedExts
]
if
not
any
(
extMatches
):
raise
PathError
(
'
{} does not end in a supported extension ({})
'
.
format
(
filename
,
'
,
'
.
join
(
allowedExts
)))
extIdx
=
extMatches
.
index
(
True
)
return
allowedExts
[
extIdx
]
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