Skip to content

Commit b008d88

Browse files
committed
fix: formatting and undefined variables
1 parent d34a669 commit b008d88

File tree

3 files changed

+38
-179
lines changed

3 files changed

+38
-179
lines changed

nitransforms/io/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
22
# vi: set ft=python sts=4 ts=4 sw=4 et:
33
"""Read and write transforms."""
4+
45
from nitransforms.io import afni, fsl, itk, lta, x5
56
from nitransforms.io.base import TransformIOError, TransformFileError
67

@@ -22,7 +23,7 @@
2223
"fs": (lta, "FSLinearTransform"),
2324
"fsl": (fsl, "FSLLinearTransform"),
2425
"afni": (afni, "AFNILinearTransform"),
25-
"x5": (x5, "X5Transform")
26+
"x5": (x5, "X5LinearTransform"),
2627
}
2728

2829

nitransforms/io/base.py

Lines changed: 0 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,11 @@
11
"""Read/write linear transforms."""
22
from pathlib import Path
33
import numpy as np
4-
import nibabel as nb
54
from nibabel import load as loadimg
65

7-
import h5py
8-
96
from ..patched import LabeledWrapStruct
107

118

12-
def get_xfm_filetype(xfm_file):
13-
path = Path(xfm_file)
14-
ext = path.suffix
15-
if ext == '.gz' and path.name.endswith('.nii.gz'):
16-
return 'nifti'
17-
18-
file_types = {
19-
'.nii': 'nifti',
20-
'.h5': 'hdf5',
21-
'.x5': 'x5',
22-
'.txt': 'txt',
23-
'.mat': 'txt'
24-
}
25-
return file_types.get(ext, 'unknown')
26-
27-
def gather_fields(x5=None, hdf5=None, nifti=None, shape=None, affine=None, header=None):
28-
xfm_fields = {
29-
"x5": x5,
30-
"hdf5": hdf5,
31-
"nifti": nifti,
32-
"header": header,
33-
"shape": shape,
34-
"affine": affine
35-
}
36-
return xfm_fields
37-
38-
def load_nifti(nifti_file):
39-
nifti_xfm = nb.load(nifti_file)
40-
xfm_data = nifti_xfm.get_fdata()
41-
shape = nifti_xfm.shape
42-
affine = nifti_xfm.affine
43-
header = getattr(nifti_xfm, "header", None)
44-
return gather_fields(nifti=xfm_data, shape=shape, affine=affine, header=header)
45-
46-
def load_hdf5(hdf5_file):
47-
storage = {}
48-
49-
def get_hdf5_items(name, x5_root):
50-
if isinstance(x5_root, h5py.Dataset):
51-
storage[name] = {
52-
'type': 'dataset',
53-
'attrs': dict(x5_root.attrs),
54-
'shape': x5_root.shape,
55-
'data': x5_root[()]
56-
}
57-
elif isinstance(x5_root, h5py.Group):
58-
storage[name] = {
59-
'type': 'group',
60-
'attrs': dict(x5_root.attrs),
61-
'members': {}
62-
}
63-
64-
with h5py.File(hdf5_file, 'r') as f:
65-
f.visititems(get_hdf5_items)
66-
if storage:
67-
hdf5_storage = {'hdf5': storage}
68-
return hdf5_storage
69-
70-
def load_x5(x5_file):
71-
load_hdf5(x5_file)
72-
73-
def load_mat(mat_file):
74-
affine_matrix = np.loadtxt(mat_file)
75-
affine = nb.affines.from_matvec(affine_matrix[:,:3], affine_matrix[:,3])
76-
return gather_fields(affine=affine)
77-
78-
def xfm_loader(xfm_file):
79-
loaders = {
80-
'nifti': load_nifti,
81-
'hdf5': load_hdf5,
82-
'x5': load_x5,
83-
'txt': load_mat,
84-
'mat': load_mat
85-
}
86-
xfm_filetype = get_xfm_filetype(xfm_file)
87-
loader = loaders.get(xfm_filetype)
88-
if loader is None:
89-
raise ValueError(f"Unsupported file type: {xfm_filetype}")
90-
return loader(xfm_file)
91-
92-
def to_filename(self, filename, fmt="X5"):
93-
"""Store the transform in BIDS-Transforms HDF5 file format (.x5)."""
94-
with h5py.File(filename, "w") as out_file:
95-
out_file.attrs["Format"] = "X5"
96-
out_file.attrs["Version"] = np.uint16(1)
97-
root = out_file.create_group("/0")
98-
self._to_hdf5(root)
99-
100-
return filename
101-
102-
def _to_hdf5(self, x5_root):
103-
"""Serialize this object into the x5 file format."""
104-
transform_group = x5_root.create_group("TransformGroup")
105-
106-
"""Group '0' containing Affine transform"""
107-
transform_0 = transform_group.create_group("0")
108-
109-
transform_0.attrs["Type"] = "Affine"
110-
transform_0.create_dataset("Transform", data=self._affine)
111-
transform_0.create_dataset("Inverse", data=np.linalg.inv(self._affine))
112-
113-
metadata = {"key": "value"}
114-
transform_0.attrs["Metadata"] = str(metadata)
115-
116-
"""sub-group 'Domain' contained within group '0' """
117-
domain_group = transform_0.create_group("Domain")
118-
#domain_group.attrs["Grid"] = self._grid
119-
#domain_group.create_dataset("Size", data=_as_homogeneous(self._reference.shape))
120-
#domain_group.create_dataset("Mapping", data=self.mapping)
121-
122-
def _from_x5(self, x5_root):
123-
variables = {}
124-
125-
x5_root.visititems(lambda name, x5_root: loader(name, x5_root, variables))
126-
127-
_transform = variables["TransformGroup/0/Transform"]
128-
_inverse = variables["TransformGroup/0/Inverse"]
129-
_size = variables["TransformGroup/0/Domain/Size"]
130-
_mapping = variables["TransformGroup/0/Domain/Mapping"]
131-
132-
return _transform, _inverse, _size, _map
133-
134-
1359
class TransformIOError(IOError):
13610
"""General I/O exception while reading/writing transforms."""
13711

nitransforms/io/x5.py

Lines changed: 36 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,39 @@
1+
# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
2+
# vi: set ft=python sts=4 ts=4 sw=4 et:
3+
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
4+
#
5+
# See COPYING file distributed along with the NiBabel package for the
6+
# copyright and license terms.
7+
#
8+
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
19
"""Read/write x5 transforms."""
2-
import warnings
10+
311
import numpy as np
4-
from scipy.io import loadmat as _read_mat, savemat as _save_mat
512
from h5py import File as H5File
6-
from nibabel import Nifti1Header, Nifti1Image
7-
from nibabel.affines import from_matvec
8-
from nitransforms.io.base import (
9-
BaseLinearTransformList,
10-
DisplacementsField,
11-
LinearParameters,
12-
TransformIOError,
13-
TransformFileError,
14-
)
15-
16-
class X5Transform:
17-
"""A string-based structure for X5 linear transforms."""
18-
19-
_transform = None
20-
21-
def __init__(self, parameters=None, offset=None):
22-
return
23-
24-
def __str__(self):
25-
return
26-
27-
@classmethod
28-
def from_filename(cls, filename):
29-
"""Read the struct from a X5 file given its path."""
30-
if str(filename).endswith(".h5"):
31-
with H5File(str(filename), 'r') as hdf:
32-
return cls.from_h5obj(hdf)
33-
34-
@classmethod
35-
def from_h5obj(cls, h5obj):
36-
"""Read the transformations in an X5 file."""
37-
xfm_list = list(h5obj.keys())
38-
39-
xfm = xfm_list["Transform"]
40-
inv = xfm_list["Inverse"]
41-
coords = xfm_list["Size"]
42-
map = xfm_list["Mapping"]
43-
44-
return xfm, inv, coords, map
45-
46-
47-
class X5LinearTransformArray(BaseLinearTransformList):
48-
"""A string-based structure for series of X5 linear transforms."""
49-
50-
_inner_type = X5Transform
51-
52-
@property
53-
def xforms(self):
54-
"""Get the list of internal X5LinearTransforms."""
55-
return self._xforms
13+
14+
15+
def to_filename(fname, xfm, moving=None):
16+
"""Store the transform in BIDS-Transforms HDF5 file format (.x5)."""
17+
with H5File(fname, "w") as out_file:
18+
out_file.attrs["Format"] = "X5"
19+
out_file.attrs["Version"] = np.uint16(1)
20+
x5_root = out_file.create_group("/0")
21+
22+
# Serialize this object into the x5 file format.
23+
transform_group = x5_root.create_group("TransformGroup")
24+
25+
# Group '0' containing Affine transform
26+
transform_0 = transform_group.create_group("0")
27+
28+
transform_0.attrs["Type"] = "Affine"
29+
transform_0.create_dataset("Transform", data=xfm.matrix)
30+
transform_0.create_dataset("Inverse", data=~xfm)
31+
32+
metadata = {"key": "value"}
33+
transform_0.attrs["Metadata"] = str(metadata)
34+
35+
# sub-group 'Domain' contained within group '0'
36+
transform_0.create_group("Domain")
37+
# domain_group.attrs["Grid"] = self._grid
38+
# domain_group.create_dataset("Size", data=_as_homogeneous(self._reference.shape))
39+
# domain_group.create_dataset("Mapping", data=self.mapping)

0 commit comments

Comments
 (0)