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

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

If I change the NRRD kinds header in my files so the first dimension becomes of the type list (instead of complex) would that make that file readable by SimpleITK? @blowekamp @dzenanz

Have your u tried the outputPixelType option?

about to try it now…

@blowekamp This is what I got when I tried:

image = sitk.ReadImage(filename, sitk.sitkVectorUInt16)

(Notice that the outp pixel type is not a keyword argument)

  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!

This is the respective NRRD header dump

__len__ = {int} 10
u'dimension' (4867413600) = {int} 4
u'encoding' (4867413792) = {str} 'gzip'
u'keyvaluepairs' (4628472432) = {dict} # Slicer metadata about segments goes here
u'kinds' (4596423152) = {list} <type 'list'>: ['complex', 'domain', 'domain', 'domain']
u'measurement frame' (4867413984) = {list} <type 'list'>: [['1', '0', '0'], ['0', '1', '0'], ['0', '0', '1']]
u'sizes' (4867413696) = {list} <type 'list'>: [2, 41, 80, 9]
u'space' (4867413360) = {str} 'right-anterior-superior'
u'space directions' (4867413456) = {list} <type 'list'>: [u'none', ['-0.5', '1.01115573674059e-10', '1.7102395547300398e-11'], ['-1.0255169999999903e-10', '-0.492998018603237', '-0.08338437295609949'], ['-1.9387071799358836e-26', '-0.50030691366964397', '2.9579921079755898']]
u'space origin' (4867413888) = {list} <type 'list'>: ['-18.165176407702127', '-1.8838383685304463', '-70.585192304157161']
u'type' (4867413504) = {str} 'unsigned char'

That should make the file readable. I think that all the other metadata is OK, but you should try to be sure. You can also change it using a text editor (e.g. Notepad++) just to see if it works, you don’t have to do it programmatically.

Hi Dženan thanks! I will try that!