ITK 5.1.2 Python XArray to image bug

Hi message board,

I’m trying to create a script in Python where I create a cine clip of a 3D volume. I want to make an itk image out of a 4D x array with data labels ‘x’, ‘y’, ‘z’, ‘t’.

I made a simple script where I repeat an image volume of a sphere at each time point. When I try to create the itk image I get an error message. My python script and error messages are below. Are there any suggestions for what the problem could be?


import numpy as np
import xarray as xr
import itk

###3D sphere
npim = np.zeros( (101,101,101) )
xx, yy, zz = np.mgrid[0:101, 0:101, 0:101]
rr = np.sqrt( (xx-50)**2 + (yy-50)**2 + (zz-50)**2 )
npim[rr < 15] = 1

###Replicate across t dimension
fourd = npim
fourd.shape = ( 101, 101,101, 1)
fourd = np.tile(fourd, [1,1,1,5])
fourdxr = xr.DataArray(fourd, dims=['x','y','z','t'])

###Create an itk image
print('Creating a 4D image')
itkim = itk.image_from_xarray(fourdxr)

Error Message:
Traceback (most recent call last):
File “”, line 24, in
itkim = itk.image_from_xarray(fourdxr)
File “/home/nick/Software/InsightToolkit-5.1.2/build/Wrapping/Generators/Python/”, line 453, in image_from_xarray
TypeError: Expecting an itkVectorD4, an int, a float, a sequence of int or a sequence of float.
Additional information:
Wrong number or type of arguments for overloaded function ‘itkImageBase4_SetSpacing’.
Possible C/C++ prototypes are:
itkImageBase4::SetSpacing(itkVectorD4 const &)
itkImageBase4::SetSpacing(double const *)
itkImageBase4::SetSpacing(float const *)

ITK script where my code sample errors out:

def image_from_xarray(data_array):
    """Convert an xarray.DataArray to an itk.Image.

    Metadata encoded with xarray_from_image is applied to the itk.Image.

    This interface is and behavior is experimental and is subject to possible
    future changes."""
    import numpy as np
    import itk

    spatial_dims = list({'z', 'y', 'x'}.intersection(set(data_array.dims)))
    spatial_dimension = len(spatial_dims)
    ordered_dims = ('z', 'y', 'x')[-spatial_dimension:]
    if ordered_dims != tuple(spatial_dims):
        raise ValueError('Spatial dimensions do not have the required order: ' + str(ordered_dims))

    is_vector = 'c' in data_array.dims
    itk_image = itk.image_view_from_array(data_array.values, is_vector=is_vector)

    origin = [0.0]*spatial_dimension
    spacing = [1.0]*spatial_dimension
    for index, dim in enumerate(spatial_dims):
        coords = data_array.coords[dim]
        if coords.shape[0] > 1:
            origin[index] = float(coords[0])
            spacing[index] = float(coords[1]) - float(coords[0])
    if 'direction' in data_array.attrs:
        direction = data_array.attrs['direction']

    return itk_image

Before version 5.2RC1, ITK’s python wrapping was compiled with dimensions 2 and 3, but not 4. That is probably the issue, which should be resolved by itk5.2rc1. Give the new version a try and report back.

I did turn on 4d wrapping in the cmake options when compiling ITK. Are issues with 4d images expected in 5.1 even when the CMake option to wrap 2;3;4 dimensional images is turned on?

I will try downloading the 5.2 version.

If you compiled yourself and turned on 4th dimension, that should have been enough. As a recent addition, image_from_xarray is not thoroughly tested.

In spacing[index] = float(coords[1]) - float(coords[0]) the float might need to be double. Or spacing somehow else adjusted to be accepted by itk_image.SetSpacing().

Hello @Nick_Rubert! :wave:

As @dzenanz, support was not yet added for a t dimension. This is added in this PR:

1 Like