22import warnings
33import numpy as np
44from scipy .io import loadmat as _read_mat , savemat as _save_mat
5+ from h5py import File as H5File
56from nibabel import Nifti1Header , Nifti1Image
67from nibabel .affines import from_matvec
78from .base import (
@@ -112,6 +113,9 @@ def from_filename(cls, filename):
112113 if str (filename ).endswith (".mat" ):
113114 with open (str (filename ), "rb" ) as fileobj :
114115 return cls .from_binary (fileobj )
116+ elif str (filename ).endswith (".h5" ):
117+ with H5File (str (filename )) as f :
118+ return cls .from_h5obj (f )
115119
116120 with open (str (filename )) as fileobj :
117121 return cls .from_string (fileobj .read ())
@@ -121,6 +125,10 @@ def from_fileobj(cls, fileobj, check=True):
121125 """Read the struct from a file object."""
122126 if fileobj .name .endswith (".mat" ):
123127 return cls .from_binary (fileobj )
128+ elif fileobj .name .endswith (".h5" ):
129+ with H5File (fileobj ) as f :
130+ return cls .from_h5obj (f )
131+
124132 return cls .from_string (fileobj .read ())
125133
126134 @classmethod
@@ -145,6 +153,11 @@ def from_matlab_dict(cls, mdict, index=0):
145153 sa ["offset" ] = mdict ["fixed" ].flatten ()
146154 return tf
147155
156+ @classmethod
157+ def from_h5obj (cls , fileobj , check = True ):
158+ """Read the struct from a file object."""
159+ raise NotImplementedError
160+
148161 @classmethod
149162 def from_ras (cls , ras , index = 0 , moving = None , reference = None ):
150163 """Create an ITK affine from a nitransform's RAS+ matrix."""
@@ -225,6 +238,9 @@ def from_filename(cls, filename):
225238 if str (filename ).endswith (".mat" ):
226239 with open (str (filename ), "rb" ) as f :
227240 return cls .from_binary (f )
241+ elif str (filename ).endswith (".h5" ):
242+ with H5File (str (filename )) as f :
243+ return cls .from_h5obj (f )
228244
229245 with open (str (filename )) as f :
230246 string = f .read ()
@@ -235,6 +251,10 @@ def from_fileobj(cls, fileobj, check=True):
235251 """Read the struct from a file object."""
236252 if fileobj .name .endswith (".mat" ):
237253 return cls .from_binary (fileobj )
254+
255+ elif fileobj .name .endswith (".h5" ):
256+ with H5File (fileobj ) as f :
257+ return cls .from_h5obj (f )
238258 return cls .from_string (fileobj .read ())
239259
240260 @classmethod
@@ -272,6 +292,31 @@ def from_string(cls, string):
272292 _self .xforms .append (cls ._inner_type .from_string ("#%s" % xfm ))
273293 return _self
274294
295+ @classmethod
296+ def from_h5obj (cls , fileobj , check = True ):
297+ """Read the struct from a file object."""
298+ h5group = fileobj ["TransformGroup" ]
299+ typo_fallback = "Transform"
300+ try :
301+ h5group ["1" ][f"{ typo_fallback } Parameters" ]
302+ except KeyError :
303+ typo_fallback = "Tranform"
304+
305+ _self = cls ()
306+ _self .xforms = []
307+ for xfm in list (h5group .values ())[1 :]:
308+ if xfm ["TransformType" ][0 ].startswith (b"AffineTransform" ):
309+ _params = np .asanyarray (xfm [f"{ typo_fallback } Parameters" ])
310+ _self .xforms .append (
311+ ITKLinearTransform (
312+ parameters = from_matvec (
313+ _params [:- 3 ].reshape (3 , 3 ), _params [- 3 :]
314+ ),
315+ offset = np .asanyarray (xfm [f"{ typo_fallback } FixedParameters" ]),
316+ )
317+ )
318+ return _self
319+
275320
276321class ITKDisplacementsField (DisplacementsField ):
277322 """A data structure representing displacements fields."""
@@ -304,8 +349,6 @@ class ITKCompositeH5:
304349 @classmethod
305350 def from_filename (cls , filename ):
306351 """Read the struct from a file given its path."""
307- from h5py import File as H5File
308-
309352 if not str (filename ).endswith (".h5" ):
310353 raise TransformFileError ("Extension is not .h5" )
311354
0 commit comments