Skip to content

ENH: Allow path-like objects for tractogram load/saving #1421

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions nibabel/streamlines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import os
import warnings
from pathlib import Path

from .array_sequence import ArraySequence
from .header import Field
Expand All @@ -22,8 +23,8 @@ def is_supported(fileobj):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object pointing
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object pointing
to a streamlines file (and ready to read from the beginning of the
header)

Expand All @@ -39,8 +40,8 @@ def detect_format(fileobj):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object pointing
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object pointing
to a tractogram file (and ready to read from the beginning of the
header)

Expand All @@ -56,8 +57,8 @@ def detect_format(fileobj):
except OSError:
pass

if isinstance(fileobj, str):
_, ext = os.path.splitext(fileobj)
if isinstance(fileobj, (str, Path)):
ext = Path(fileobj).suffix
return FORMATS.get(ext.lower())

return None
Expand All @@ -68,8 +69,8 @@ def load(fileobj, lazy_load=False):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object
pointing to a streamlines file (and ready to read from the beginning
of the streamlines file's header).
lazy_load : {False, True}, optional
Expand Down Expand Up @@ -106,7 +107,7 @@ def save(tractogram, filename, **kwargs):
provided keyword arguments.
If :class:`TractogramFile` object, the file format is known and will
be used to save its content to `filename`.
filename : str
filename : path-like object
Name of the file where the tractogram will be saved.
\*\*kwargs : keyword arguments
Keyword arguments passed to :class:`TractogramFile` constructor.
Expand Down
12 changes: 6 additions & 6 deletions nibabel/streamlines/tck.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ def load(cls, fileobj, lazy_load=False):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object in
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object in
binary mode pointing to TCK file (and ready to read from the
beginning of the TCK header). Note that calling this function
does not change the file position.
Expand Down Expand Up @@ -167,8 +167,8 @@ def save(self, fileobj):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object in
fileobj : path-like or or file-like object
If path-like, a filename; otherwise an open file-like object in
binary mode pointing to TCK file (and ready to write from the
beginning of the TCK header data).
"""
Expand Down Expand Up @@ -403,8 +403,8 @@ def _read(cls, fileobj, header, buffer_size=4):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object in
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object in
binary mode pointing to TCK file (and ready to read from the
beginning of the TCK header). Note that calling this function
does not change the file position.
Expand Down
29 changes: 28 additions & 1 deletion nibabel/streamlines/tests/test_streamlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import warnings
from io import BytesIO
from os.path import join as pjoin
from pathlib import Path

import numpy as np
import pytest
Expand Down Expand Up @@ -90,6 +91,7 @@ def test_is_supported_detect_format(tmp_path):
assert not nib.streamlines.is_supported('')
assert nib.streamlines.detect_format(f) is None
assert nib.streamlines.detect_format('') is None
assert nib.streamlines.detect_format(Path('')) is None

# Valid file without extension
for tfile_cls in FORMATS.values():
Expand Down Expand Up @@ -128,6 +130,12 @@ def test_is_supported_detect_format(tmp_path):
assert nib.streamlines.is_supported(f)
assert nib.streamlines.detect_format(f) == tfile_cls

# Good extension, Path only
for ext, tfile_cls in FORMATS.items():
f = Path('my_tractogram' + ext)
assert nib.streamlines.is_supported(f)
assert nib.streamlines.detect_format(f) == tfile_cls

# Extension should not be case-sensitive.
for ext, tfile_cls in FORMATS.items():
f = 'my_tractogram' + ext.upper()
Expand All @@ -149,7 +157,7 @@ def test_load_empty_file(self):
with pytest.warns(Warning) if lazy_load else error_warnings():
assert_tractogram_equal(tfile.tractogram, DATA['empty_tractogram'])

def test_load_simple_file(self):
def test_load_simple_file_str(self):
for lazy_load in [False, True]:
for simple_filename in DATA['simple_filenames']:
tfile = nib.streamlines.load(simple_filename, lazy_load=lazy_load)
Expand All @@ -163,6 +171,20 @@ def test_load_simple_file(self):
with pytest.warns(Warning) if lazy_load else error_warnings():
assert_tractogram_equal(tfile.tractogram, DATA['simple_tractogram'])

def test_load_simple_file_path(self):
for lazy_load in [False, True]:
for simple_filename in DATA['simple_filenames']:
tfile = nib.streamlines.load(Path(simple_filename), lazy_load=lazy_load)
assert isinstance(tfile, TractogramFile)

if lazy_load:
assert type(tfile.tractogram), Tractogram
else:
assert type(tfile.tractogram), LazyTractogram

with pytest.warns(Warning) if lazy_load else error_warnings():
assert_tractogram_equal(tfile.tractogram, DATA['simple_tractogram'])

def test_load_complex_file(self):
for lazy_load in [False, True]:
for complex_filename in DATA['complex_filenames']:
Expand Down Expand Up @@ -205,6 +227,11 @@ def test_save_tractogram_file(self):
tfile = nib.streamlines.load('dummy.trk', lazy_load=False)
assert_tractogram_equal(tfile.tractogram, tractogram)

with InTemporaryDirectory():
nib.streamlines.save(trk_file, Path('dummy.trk'))
tfile = nib.streamlines.load('dummy.trk', lazy_load=False)
assert_tractogram_equal(tfile.tractogram, tractogram)

def test_save_empty_file(self):
tractogram = Tractogram(affine_to_rasmm=np.eye(4))
for ext in FORMATS:
Expand Down
12 changes: 6 additions & 6 deletions nibabel/streamlines/trk.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ def load(cls, fileobj, lazy_load=False):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object
pointing to TRK file (and ready to read from the beginning
of the TRK header). Note that calling this function
does not change the file position.
Expand Down Expand Up @@ -401,8 +401,8 @@ def save(self, fileobj):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object
pointing to TRK file (and ready to write from the beginning
of the TRK header data).
"""
Expand Down Expand Up @@ -550,8 +550,8 @@ def _read_header(fileobj):

Parameters
----------
fileobj : string or file-like object
If string, a filename; otherwise an open file-like object
fileobj : path-like or file-like object
If path-like, a filename; otherwise an open file-like object
pointing to TRK file (and ready to read from the beginning
of the TRK header). Note that calling this function
does not change the file position.
Expand Down
Loading