Trouble running pyradiomics on .nrrd files

567 views
Skip to first unread message

Michal Sosinski

unread,
Nov 10, 2017, 4:21:52 AM11/10/17
to pyradiomics
Hello,

This is my first try with pyradiomics. Example images work just fine, but when I try to use .nrrd images created from LIDC/IDRI dataset, I come up to following error:

>sitk::ERROR: Both images for LabelStatisticsImageFilter don't match type or dimension!

When I try to use resampleMask.py on same files, I come up to following error:

>sitk::ERROR: Length of input (9) does not match matrix dimensions (2, 2).

When I try to follow steps from https://groups.google.com/forum/#!topic/pyradiomics/QLdD_qEw3PY , I come up to following error:

>sitk::ERROR: Pixel type: 8-bit unsigned integer is not supported in 3D byN3itk6simple21JoinSeriesImageFilterE

Seems like SimpleITK is not digesting my files. Does anybody have an idea what to do next?

Thanks in advance,
Michał

Joost van Griethuysen

unread,
Nov 10, 2017, 4:34:12 AM11/10/17
to pyradiomics
Dear Michal,

What is your input? (i.e. file type, 2D/3D, grayscale color?)
The first error is indeed that there is a mismatch between your mask and image, the second that it's unable to correct this and the last error is a datatype error.

Can you please paste the ouput if you do the following (for both you image AND mask):

Run python, and in python run:

import SimpleITK as sitk
im = sitk.ReadImage(r'<PATH/TO/IMAGE>')
print(im)

Regards,

Joost van Griethuysen

Op vrijdag 10 november 2017 10:21:52 UTC+1 schreef Michal Sosinski:

Michal Sosinski

unread,
Nov 10, 2017, 4:35:44 AM11/10/17
to pyradiomics
I enclose the files I try to analyze:
139.nrrd
139_mask.nrrd

Michal Sosinski

unread,
Nov 10, 2017, 4:39:48 AM11/10/17
to pyradiomics
Thank you for a reply and thanks a lot for this lib. Here's the output:

Image (0x1c86610)
  RTTI typeinfo:   itk::Image<unsigned char, 3u>
  Reference Count: 1
  Modified Time: 934
  Debug: Off
  Object Name:
  Observers:
    none
  Source: (none)
  Source output name: (none)
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 921
  UpdateMTime: 933
  RealTimeStamp: 0 seconds
  LargestPossibleRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [3, 420, 420]
  BufferedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [3, 420, 420]
  RequestedRegion:
    Dimension: 3
    Index: [0, 0, 0]
    Size: [3, 420, 420]
  Spacing: [1, 1, 1]
  Origin: [0, 0, 0]
  Direction:
1 0 0
0 1 0
0 0 1

  IndexToPointMatrix:
1 0 0
0 1 0
0 0 1

  PointToIndexMatrix:
1 0 0
0 1 0
0 0 1

  Inverse Direction:
1 0 0
0 1 0
0 0 1

  PixelContainer:
    ImportImageContainer (0x1cebed0)
      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned char>
      Reference Count: 1
      Modified Time: 930
      Debug: Off
      Object Name:
      Observers:
        none
      Pointer: 0x283fdb0
      Container manages memory: true
      Size: 529200
      Capacity: 529200

Michal Sosinski

unread,
Nov 10, 2017, 4:41:03 AM11/10/17
to pyradiomics
and here's output for the mask:

Image (0x26f43a0)
  RTTI typeinfo:   itk::Image<unsigned char, 2u>
  Reference Count: 1
  Modified Time: 1104

  Debug: Off
  Object Name:
  Observers:
    none
  Source: (none)
  Source output name: (none)
  Release Data: Off
  Data Released: False
  Global Release Data: Off
  PipelineMTime: 1092
  UpdateMTime: 1103
  RealTimeStamp: 0 seconds
  LargestPossibleRegion:
    Dimension: 2
    Index: [0, 0]
    Size: [420, 420]
  BufferedRegion:
    Dimension: 2
    Index: [0, 0]
    Size: [420, 420]
  RequestedRegion:
    Dimension: 2
    Index: [0, 0]
    Size: [420, 420]
  Spacing: [1, 1]
  Origin: [0, 0]
  Direction:
1 0

0 1

  IndexToPointMatrix:
1 0
0 1

  PointToIndexMatrix:
1 0
0 1

  Inverse Direction:
1 0
0 1

  PixelContainer:
    ImportImageContainer (0x22173b0)

      RTTI typeinfo:   itk::ImportImageContainer<unsigned long, unsigned char>
      Reference Count: 1
      Modified Time: 1100

      Debug: Off
      Object Name:
      Observers:
        none
      Pointer: 0x28c10f0
      Container manages memory: true
      Size: 176400
      Capacity: 176400

Joost van Griethuysen

unread,
Nov 10, 2017, 5:13:53 AM11/10/17
to pyradiomics
Hello Michal,

I think I know the cause of your errors. 
The first error is indeed the mismatch (image is 3D, mask is 2D). This also caused the resampleMask script to fail, because that still assumes the image and mask to have the same dimensionality.
As to your last error, that is caused because the JoinSeries filter doesn't like the unsigned char datatype, why this is I don't know.
I can help you to fix it though. You can use the JoinSeries by first using "sitk.Cast(<Image>, sitk.sitkUInt16)", where <Image> is the simpleITK image object of your mask.

However, I saw that your image's dimension are differently ordered: x, y, z sizes are 3, 420, 420. Therefore, you want your mask to end up as 1, 420,420.

This is possible, but pay attention, as this will load the mask on THE FIRST SLICE OF THE IMAGE. I simply do not have the information to determine which slice the mask corresponds to.
Is there a specific reason your image has 3 slices?

anyway, this is a possible way to get your mask to correspond to your images' first slide (or any other slide, see comments in the script). All code lines below are run inside a python interpreter

import SimpleITK as sitk
import numpy as np

im = sitk.ReadImage(r'<path/to/image.nrrd>')
ma = sitk.ReadImage(r'<path/to/mask.nrrd>')

ma_arr = sitk.GetArrayFromImage(ma)
new_arr = np.zeros((ma_arr.shape[0], ma_arr.shape[1], 3), dtype='uint16')  # should be the same shape as the array from your image, in z, x, y (reversed from the dimensions you see printed, those are x, y, z)

slice_num = 0  # this indicates on which slice the mask should be situated
new_arr[:, :, slice_num] = ma_arr

# optional, ensure mask is on all slices:
new_arr[:, :, :] = ma_arr[:, :, None]  # IMPORTANT, don't forget the [:, :, :] behind new_arr, otherwise your dimension will be incorrect!

new_ma = sitk.GetImageFromArray(new_arr)
new_ma.CopyInformation(im)

sitk.WriteImage(new_ma, r'<path/to/new/mask.nrrd>', True)


Regards,

Joost

Op vrijdag 10 november 2017 10:21:52 UTC+1 schreef Michal Sosinski:
Hello,

Michal Sosinski

unread,
Nov 10, 2017, 5:52:49 AM11/10/17
to pyradiomics
>Is there a specific reason your image has 3 slices?

I have no idea, I will ask the person who provided me with images.

Your code did work, thank you very much, I created a new mask file and extractor extracted all the features.  However, I did not use sitk.JoinSeries and it still did work. Did you mean that after creating a new mask file using your code, I should run sitk.JoinSeries on it? I can't really see the place where your code turns 2D image to 3D one. Or is it enough to apply 2D mask on first slice of 3D image and this basically happend?

Thanks a lot again,
Michał

Joost van Griethuysen

unread,
Nov 10, 2017, 6:00:15 AM11/10/17
to pyradiomics
You don't need the JoinSeries. When you first create the new_arr using np.zeros, you specify a 3D shape. Then with "new_arr[:, :, slice_num] = ma_arr" or "new_arr[:, :, :] = ma_arr[:, :, None]" you assign your 2D mask slice to either the specified slice, or all slices, respectively. From this point on, your mask is 3D. You then recreate a SimpleITK image object out of it and set all meta data to be equal to your image by using "CopyInformation".

Regards,

Joost

Op vrijdag 10 november 2017 11:52:49 UTC+1 schreef Michal Sosinski:

Andrey Fedorov

unread,
Nov 10, 2017, 11:20:05 AM11/10/17
to pyradiomics
Michal, did you try to load your image and label into a viewer to confirm the data looks ok?

We recommend 3D Slicer for visualizing images and segmentation overlay. It is particularly important to do this when you are just starting with the library.

I did look at your dataset, and I am not sure it is correct. Your image appears to contain 3 identical slices and is not oriented properly, and your mask appears to be empty.

Michal Sosinski

unread,
Nov 13, 2017, 5:43:36 PM11/13/17
to pyradiomics


Michal, did you try to load your image and label into a viewer to confirm the data looks ok?

No, but I will do it.
 

We recommend 3D Slicer for visualizing images and segmentation overlay. It is particularly important to do this when you are just starting with the library.

I did look at your dataset, and I am not sure it is correct. Your image appears to contain 3 identical slices and is not oriented properly, and your mask appears to be empty.

Three slices are probably because it's RGB and each slice is one canal.

Masks seem to fit nodules when I preview them in .png.

I wonder if it might be a reason why I have different values for first order features when I extract them from different levels of lung. The whole nodule is seen on 12 slices and I have run first order extractor for each one. When I compare the results, they're different.

Cheers,
Michał

Andrey Fedorov

unread,
Nov 13, 2017, 5:48:12 PM11/13/17
to Michal Sosinski, pyradiomics
Is there any reason to create .png files for the input DICOM data?

Can we take a step back and get some idea for the bigger picture of what you want to accomplish? It might be more efficient to start there and discuss the processing strategy from the start.

--
You received this message because you are subscribed to the Google Groups "pyradiomics" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyradiomics+unsubscribe@googlegroups.com.
To post to this group, send email to pyrad...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyradiomics/89b3e87d-808d-453f-b1d9-64fd4a89893a%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Michal Sosinski

unread,
Nov 14, 2017, 5:24:17 PM11/14/17
to pyradiomics
Hi,

The story is pretty simple: A friend of mine is using LIDC/IDRI dataset to train his deep learning model to detect nodules. This task also requires him to store images and masks in separate files, so I asked him if he could share some with me so I can learn pyradiomics using them. He sent me png files, but then I realised they're incompatible with SimpleITK and asked him to dump images and masks in .nrrd not .png. Then, with help of Joost from your team, I made the .nrrd images and masks compatible with each other and run first experiment. Now I have one nodule on 12 slices, and for each slice first order features of the nodule are different. Is that fine? What variation in radiomic features is acceptable for a single nodule?

Thanks,


W dniu poniedziałek, 13 listopada 2017 23:48:12 UTC+1 użytkownik Andrey Fedorov napisał:
Is there any reason to create .png files for the input DICOM data?

Can we take a step back and get some idea for the bigger picture of what you want to accomplish? It might be more efficient to start there and discuss the processing strategy from the start.
On Mon, Nov 13, 2017 at 5:43 PM, Michal Sosinski <michal.l...@gmail.com> wrote:


Michal, did you try to load your image and label into a viewer to confirm the data looks ok?

No, but I will do it.
 

We recommend 3D Slicer for visualizing images and segmentation overlay. It is particularly important to do this when you are just starting with the library.

I did look at your dataset, and I am not sure it is correct. Your image appears to contain 3 identical slices and is not oriented properly, and your mask appears to be empty.

Three slices are probably because it's RGB and each slice is one canal.

Masks seem to fit nodules when I preview them in .png.

I wonder if it might be a reason why I have different values for first order features when I extract them from different levels of lung. The whole nodule is seen on 12 slices and I have run first order extractor for each one. When I compare the results, they're different.

Cheers,
Michał

--
You received this message because you are subscribed to the Google Groups "pyradiomics" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyradiomics...@googlegroups.com.

To post to this group, send email to pyrad...@googlegroups.com.

Joost van Griethuysen

unread,
Nov 15, 2017, 4:06:27 AM11/15/17
to pyradiomics
Hi,

Is the output from the model of your friend a png file and did you have to convert that? Usually, we stay in nrrd or niftii, because this also preserves the transformation to real-world coordinates (i.e. spacing, direction and origin). Moreover, for 1 nodule, do you have 1 mask file (for all slices) or 1 file per slice of each nodule?

That radiomics variables are different between nodules and between slices is kinda what we're going for. The question is then if those differences are correlated to the outcome we're trying to predict. Even between slices there may be differences (different parts of the nodule can express different heterogeneity). Still, when you're predicitin a lesion-based score (for example the malignancy rating in the LIDC dataset), you need to have 1 value per lesion. PyRadiomics generally calculates one value per feature per lesion, provided that the lesion is contained in 1 mask. If you have multiple masks, you can average over the values to get your lesion-value, but I'd advise using 1 mask per lesion, not per slice (this also enables you to calculate texture in 3D).

Regards,

Joost

Op dinsdag 14 november 2017 23:24:17 UTC+1 schreef Michal Sosinski:
Reply all
Reply to author
Forward
0 new messages