1
1
"""Read/write ITK transforms."""
2
+
2
3
import warnings
3
4
import numpy as np
4
5
from scipy .io import loadmat as _read_mat , savemat as _save_mat
@@ -138,8 +139,7 @@ def from_matlab_dict(cls, mdict, index=0):
138
139
sa = tf .structarr
139
140
140
141
affine = mdict .get (
141
- "AffineTransform_double_3_3" ,
142
- mdict .get ("AffineTransform_float_3_3" )
142
+ "AffineTransform_double_3_3" , mdict .get ("AffineTransform_float_3_3" )
143
143
)
144
144
145
145
if affine is None :
@@ -196,7 +196,7 @@ def from_string(cls, string):
196
196
lines = lines [1 :] # Drop banner with version
197
197
198
198
parameters = np .eye (4 , dtype = "f4" )
199
- sa ["index" ] = int (lines [0 ][lines [0 ].index ("T" ):].split ()[1 ])
199
+ sa ["index" ] = int (lines [0 ][lines [0 ].index ("T" ) :].split ()[1 ])
200
200
sa ["offset" ] = np .genfromtxt (
201
201
[lines [3 ].split (":" )[- 1 ].encode ()], dtype = cls .dtype ["offset" ]
202
202
)
@@ -337,7 +337,7 @@ def from_image(cls, imgobj):
337
337
hdr = imgobj .header .copy ()
338
338
shape = hdr .get_data_shape ()
339
339
340
- if len (shape ) != 5 or shape [- 2 ] != 1 or not shape [- 1 ] in (2 , 3 ):
340
+ if len (shape ) != 5 or shape [- 2 ] != 1 or shape [- 1 ] not in (2 , 3 ):
341
341
raise TransformFileError (
342
342
'Displacements field "%s" does not come from ITK.'
343
343
% imgobj .file_map ["image" ].filename
@@ -347,10 +347,10 @@ def from_image(cls, imgobj):
347
347
warnings .warn ("Incorrect intent identified." )
348
348
hdr .set_intent ("vector" )
349
349
350
- field = np .squeeze (np .asanyarray (imgobj .dataobj ))
350
+ field = np .squeeze (np .asanyarray (imgobj .dataobj )). transpose ( 2 , 1 , 0 , 3 )
351
351
field [..., (0 , 1 )] *= - 1.0
352
352
353
- return imgobj .__class__ (field , imgobj .affine , hdr )
353
+ return imgobj .__class__ (field , LPS @ imgobj .affine , hdr )
354
354
355
355
@classmethod
356
356
def to_image (cls , imgobj ):
@@ -359,10 +359,9 @@ def to_image(cls, imgobj):
359
359
hdr = imgobj .header .copy ()
360
360
hdr .set_intent ("vector" )
361
361
362
- warp_data = imgobj .get_fdata ().reshape (imgobj .shape [:3 ] + (1 , imgobj .shape [- 1 ]))
363
- warp_data [..., (0 , 1 )] *= - 1
364
-
365
- return imgobj .__class__ (warp_data , imgobj .affine , hdr )
362
+ field = imgobj .get_fdata ().transpose (2 , 1 , 0 , 3 )[..., None , :]
363
+ field [..., (0 , 1 )] *= - 1.0
364
+ return imgobj .__class__ (field , LPS @ imgobj .affine , hdr )
366
365
367
366
368
367
class ITKCompositeH5 :
@@ -410,21 +409,16 @@ def from_h5obj(cls, fileobj, check=True, only_linear=False):
410
409
directions = np .reshape (_fixed [9 :], (3 , 3 ))
411
410
affine = from_matvec (directions * zooms , offset )
412
411
# ITK uses Fortran ordering, like NIfTI, but with the vector dimension first
413
- field = np .moveaxis (
414
- np .reshape (
415
- xfm [f"{ typo_fallback } Parameters" ], (3 , * shape .astype (int )), order = 'F'
416
- ),
417
- 0 ,
418
- - 1 ,
419
- )
420
- field [..., (0 , 1 )] *= - 1.0
412
+ # In practice, this seems to work (see issue #171)
413
+ field = np .reshape (
414
+ xfm [f"{ typo_fallback } Parameters" ], (* shape .astype (int ), 3 )
415
+ ).transpose (2 , 1 , 0 , 3 )
416
+
421
417
hdr = Nifti1Header ()
422
418
hdr .set_intent ("vector" )
423
419
hdr .set_data_dtype ("float" )
424
420
425
- xfm_list .append (
426
- Nifti1Image (field .astype ("float" ), LPS @ affine , hdr )
427
- )
421
+ xfm_list .append (Nifti1Image (field .astype ("float" ), affine , hdr ))
428
422
continue
429
423
430
424
raise TransformIOError (
0 commit comments