Skip to content

Commit 8e50969

Browse files
committed
fix: process exceptions when trying to open X5
1 parent eeb4d5d commit 8e50969

File tree

4 files changed

+35
-13
lines changed

4 files changed

+35
-13
lines changed

nitransforms/io/x5.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,21 @@ def to_filename(fname: str | Path, x5_list: List[X5Transform]):
140140

141141
def from_filename(fname: str | Path) -> List[X5Transform]:
142142
"""Read a list of :class:`X5Transform` objects from an X5 HDF5 file."""
143-
with h5py.File(str(fname), "r") as in_file:
144-
if in_file.attrs.get("Format") != "X5":
145-
raise ValueError("Input file is not in X5 format")
146-
147-
tg = in_file["TransformGroup"]
148-
return [
149-
_read_x5_group(node)
150-
for _, node in sorted(tg.items(), key=lambda kv: int(kv[0]))
151-
]
143+
try:
144+
with h5py.File(str(fname), "r") as in_file:
145+
if in_file.attrs.get("Format") != "X5":
146+
raise TypeError("Input file is not in X5 format")
147+
148+
tg = in_file["TransformGroup"]
149+
return [
150+
_read_x5_group(node)
151+
for _, node in sorted(tg.items(), key=lambda kv: int(kv[0]))
152+
]
153+
except OSError as err:
154+
if "file signature not found" in err.args[0]:
155+
raise TypeError("Input file is not HDF5.")
156+
157+
raise # pragma: no cover
152158

153159

154160
def _read_x5_group(node) -> X5Transform:

nitransforms/linear.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"""Linear transforms."""
1010

1111
import warnings
12+
from collections import namedtuple
1213
import numpy as np
1314
from pathlib import Path
1415

@@ -187,9 +188,18 @@ def from_filename(
187188
if fmt and fmt.upper() == "X5":
188189
x5_xfm = load_x5(filename)[x5_position]
189190
Transform = cls if x5_xfm.array_length == 1 else LinearTransformsMapping
190-
if x5_xfm.domain:
191-
# override reference
192-
raise NotImplementedError
191+
if (
192+
x5_xfm.domain
193+
and not x5_xfm.domain.grid
194+
and len(x5_xfm.domain.size) == 3
195+
): # pragma: no cover
196+
raise NotImplementedError(
197+
"Only 3D regularly gridded domains are supported"
198+
)
199+
elif x5_xfm.domain:
200+
# Override reference
201+
Domain = namedtuple("Domain", "affine shape")
202+
reference = Domain(x5_xfm.domain.mapping, x5_xfm.domain.size)
193203

194204
return Transform(x5_xfm.transform, reference=reference)
195205

nitransforms/tests/test_linear.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ def test_linear_to_x5(tmpdir, store_inverse):
265265

266266
aff.to_filename("export1.x5", x5_inverse=store_inverse)
267267

268+
# Test round trip
269+
assert aff == nitl.Affine.from_filename("export1.x5", fmt="X5")
270+
268271
# Test with Domain
269272
img = nb.Nifti1Image(np.zeros((2, 2, 2), dtype="float32"), np.eye(4))
270273
img_path = Path(tmpdir) / "ref.nii.gz"
@@ -275,6 +278,9 @@ def test_linear_to_x5(tmpdir, store_inverse):
275278
assert node.domain.size == aff.reference.shape
276279
aff.to_filename("export2.x5", x5_inverse=store_inverse)
277280

281+
# Test round trip
282+
assert aff == nitl.Affine.from_filename("export2.x5", fmt="X5")
283+
278284
# Test with Jacobian
279285
node.jacobian = np.zeros((2, 2, 2), dtype="float32")
280286
io.x5.to_filename("export3.x5", [node])

nitransforms/tests/test_x5.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ def test_from_filename_invalid(tmp_path):
7373
with H5File(fname, "w") as f:
7474
f.attrs["Format"] = "NOTX5"
7575

76-
with pytest.raises(ValueError):
76+
with pytest.raises(TypeError):
7777
from_filename(fname)

0 commit comments

Comments
 (0)