reading segmentation file from Slicer (NRRD) with multiple segments with SimpleITK shows Exception

Hello!

I segmented two prostate lesions in Slicer and saved the segmentation as NRRD.

I am trying to read this file using SimpleITK but I am getting the following error message:

File "/Users/odin/anaconda/lib/python2.7/site-packages/SimpleITK/SimpleITK.py", line 8332, in ReadImage
    return _SimpleITK.ReadImage(*args)
RuntimeError: Exception thrown in SimpleITK ReadImage: /scratch/dashboards/SimpleITK-OSX10.6-intel-pkg/SimpleITK/Code/IO/src/sitkImageReaderBase.cxx:285:
sitk::ERROR: Only Complex image with float and double are supported!

However I can perfectly read segmentation files with one segment. Is this a limitation of the current version?
When looking at the NRRD headers:

dimension = 4
sizes= [2, 41, 80, 9]
kinds=['complex', 'domain', 'domain', 'domain']

So I know I have my two segments there (first index of sizes gives the number of segments) and that actually matches with the data array.
Does anyone know about this problem?

Thanks,

Diego

Hello Diego,

How was this image created? I’m guessing the “type” is some thing like “unsigned short”. Seems not appropriate to save a multi-segmentation image with a “complex type”.

Technically in C++ std::complex_short has undefined behavior. So SimpleITK only support std::complex of float and double as the error message says.

Perhaps the NRRD author (@glk) or a Slicer developer (@fedorov @lassoan) could tell us if that is a normal file type or not.

2 Likes

This is another (in addition to multivolumes, and perhaps other adaptations) Slicer-specific use of NRRD. @lassoan is the man with the answers.

1 Like

Why was complex chosen over some type of vector?

I don’t know the background, but I am sure Andras will have the answer.

@Diego_C to solve your immediate problem, you can export individual segments as label maps using Segmentations module of Slicer, and save those in separate 3-d files that ITK will know how to deal with.

You can even export both of the segments into a single label map 3d file, since they do not overlap.

1 Like

A potential work around is to specify the pixel type when reading the image:

sitk.ReadImage("complex_short.nrrd", outputPixelType=sitkVectorUInt16)

I have not tried it, but I expect it to work.

Hi Bradley,

I don’t know. These are multi-segment segmentations without any custom code, just saved directly from Slicer3D.

Diego

Hi Andrey!

I totally get the workaround you propose it makes sense since having separate nrrd files for each segment will give SimpleITK easily recognizable nrrd headers. However I can’t implement it! I have about 900+ segmentations already from 3 different radiologists… so I couldn’t possibly do this by hand.

Last night I develop code that reads these multi-segment segmentations which in nrrd terms means a 4-dimensional array where the first index indicates the segment s (like this [s, x, y, z])

And generates a SimpleITK image with for each segment. I made sure that the metadata for each image was preserved so each image has its origin, spacing, direction, etc.

I wonder if there is a way for me to contribute this code ??
multi-volume nrrd (like in this case) seems to be a current limitation for sitk.ReadImage

Diego

2 Likes

Thanks Bradley I will give it a try and let you know. I am away from my computer for Easter Friday (typing all of this on my phone) will check this weekend.

1 Like

@Diego_C your explanation makes total sense, I didn’t realize the scale is so big!

I wonder if anything would work differently if you replaced complex with vector or something else in the NRRD header …

When Slicer saves segmentation (4D volume) to file then it uses vtkTeemNRRDWriter, which unfortunately tries to be smart and guess the axis type from the number of vector components - for 2 components it assumes that it is a complex number (https://github.com/Slicer/Slicer/blob/master/Libs/vtkTeem/vtkTeemNRRDWriter.cxx#L90). I’ll fix this in Slicer - it’ll always use “vector” as axis kind.

3 Likes

I am pondering if SimpleITK should automatically load complex of integers as plain vector images with a warning, or the produces error should just suggest adding the “outputPixelType” parameter.

How long has Slicer been producing this type of image?

How long has Slicer been producing this type of image?

For about a year. The problem occurs only when there are two (or few other) components. Also, many people kept using the old editor and simple labelmap format for a while. So, probably the number of “complex” files are quite low. However, it would be still useful to make SimpleITK be able to load any kinds of axis.

1 Like

The problem is that SimpleITK supports complex type, but that image is not a kind of complex type SimpleITK supports (and appropriately gives an error message). Segmentations module should always write vector or list for the first dimension.

2 Likes

Yes, I completely agree. I’ve committed a fix, which will be included in tomorrow’s nightly build:
https://github.com/Slicer/Slicer/commit/a5cb03fec66823d8ddf5e4f5942d988895781833

Existing segmentation file that have two segments (and thus the incorrect “complex” kind) can be fixed by loading the file into Slicer and saving it.

2 Likes

If SimpleITK can only support complex with float components then when a complex image with int components is read then you can convert the values to float. However, such images should be very rare, so supporting this may not worth the implementation, testing, and maintenance effort.

1 Like

Thank you @lassoan for your help. I have 900+ segmentations by 3 radiologist at the moment so doing this change in the headers by loading each file in Slicer is not feasible. However, as I mentioned before I wrote some code that handles these multi-segmentations correctly and generates a SimpleITK image for each. I would be happy to contribute this code as a work around for people with the same problem.

What does the code do? Changes kind from “complex” to “list” in the nrrd file header?

Actually that was going to be my next script while you guys and gals update Slicer :smile:.

No, this code loads the multi-segment segmentation NRRD using pynrrd and then for each volume creates a SimpleITK image observing the appropriate metadata.

1 Like