# dicom nrrd nifti spacing, origin mismatch.

**URL:** <https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311>\
**Category:** Uncategorized\
**Created:** [August 4, 2021, 3:06pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311 "2021-08-04T15:06:14Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 4, 2021, 3:06pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/1 "2021-08-04T15:06:14Z")

</div>

Hello I am working with dicom and nrrd image file formats. Usually nrrd files are segmentations and in different spacing and origin compared to the dicoms. So my workflow is:

1. resample the nrrd file on dicom to match dicom’s spacing and origin and other image properties.
2. Then perform some morphological operation on the resampled nrrd file.
3. convert both dicom and resampled nrrd to nifti format maintaining the properties.

For these 3 steps I am using the following:

```auto
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dcmCasePath)
reader.SetFileNames(dicom_names)
dicom = reader.Execute() 

nrrd = sitk.ReadImage(nrrdFilePath)

```

use the following function to resample nrrd on dicom:

```auto
def Realign(self, image, reference_image, def_value=0.0):
        """
        :param image: image to resample or align(.nrrd files)
        :param reference_image: .dcm files
        :param def_value: values to fill the resampled image
        :return: aligned image that matches reference image origin, spacing etc.
        """
        return sitk.Resample(image,
                             reference_image,
                             sitk.Transform(),
                             sitk.sitkLinear,
                             def_value,
                             reference_image.GetPixelID())
data = [dicom, nrrd]
alignedNrd= Realign(data[1], data[0])

```

Then I perform some morphological operations on NumPy-based aligned image.

```auto
SegBN = np.zeros_like(sitk.GetArrayFromImage(alignedNrd))
SegBN[np.where(sitk.GetArrayFromImage(alignedNrd) > 0)] = 1

```

Finally saving the image in nifti:

```auto
nrd2niiPath = os.path.splitext(nrdpath)[0]+'_{}'.format(ig)+'.nii.gz'
sitk.WriteImage(sitk.GetImageFromArray(SegBN), nrd2niiPath)
dcm2niiPath = os.path.join(dcmPath, os.path.basename(dcmPath)) +'.nii.gz'
sitk.WriteImage(dicom, dcm2niiPath)

```

But the spacing and origin in the nifti images are totally different. Despite the nrrd image was resampled in reference to the dicom.

To check:

```auto
dcmimage.GetSpacing(), alignedNrrd.GetSpacing()
((0.3613280058, 0.3613280058, 0.625), (0.3613280058, 0.3613280058, 0.625))

dcmimage.GetOrigin(), alignedNrrd.GetOrigin()
((-69.19999695, -109.8000031, -240.375),
 (-69.19999695, -109.8000031, -240.375))

dcmimage.GetSize(), alignedNrrd.GetSize()
((512, 512, 224), (512, 512, 224))

imgnb.get_affine(), segnb.get_affine()
(array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]),
 array([[-1., 0., 0., -0.],
        [0., -1., 0., -0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.]]))

```

As it can be seen the nifti formats are in different spacings.  
To visualize the nifti image and segmentation separately in ITKsnap:

 ![realigngonewrong](https://discourse.itk.org/uploads/default/original/2X/a/af40ebecf9b12e09810b74dc2d27115f0dd495cb.png)  
For some reason, the segmentation is isotropic and completely in different spacing and origin, despite the image size are the same.

What is happening after the morphological operation or saving niftis that changes the image origin, spacing and all?

---

<div class="post-metadata">

**Author:** ![dchen](https://discourse.itk.org/user_avatar/discourse.itk.org/dchen/32/34_2.png) [@dchen](https://discourse.itk.org/u/dchen)\
**Post date:** [August 4, 2021, 3:14pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/2 "2021-08-04T15:14:37Z")

</div>

Converting your image to NumPy arrays loses all the metadata information.

---

<div class="post-metadata">

**Author:** ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)\
**Post date:** [August 4, 2021, 3:16pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/3 "2021-08-04T15:16:59Z")

</div>

When you create `SegBN`, you lose image metadata. Try this:

```auto
SegBN = sitk.GetArrayFromImage(alignedNrd)
SegBN[np.where(sitk.GetArrayFromImage(alignedNrd) > 0)] = 1

```

---

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 4, 2021, 4:34pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/5 "2021-08-04T16:34:15Z")

</div>

It didn’t solve the spacing problem.

```auto
>> imgnb.affine, segnb.affine
(array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]),
 array([[-1., 0., 0., -0.],
        [0., -1., 0., -0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.]]))

```

Additionally, I can’t change the morphological operations. I have to create a binary mask, and the one you suggested creates a map with 3 values(-1, 0, 1).

---

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 4, 2021, 4:35pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/6 "2021-08-04T16:35:32Z")

</div>

So are there ways to perform morphological operations without converting resampled nrrd images to NumPy arrays?

---

<div class="post-metadata">

**Author:** ![dzenanz](https://discourse.itk.org/user_avatar/discourse.itk.org/dzenanz/32/1093_2.png) [@dzenanz](https://discourse.itk.org/u/dzenanz)\
**Post date:** [August 4, 2021, 4:35pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/7 "2021-08-04T16:35:53Z")

</div>

Perhaps than copy metadata after you create the segmentation:

```auto
SegITK = sitk.GetImageFromArray(SegBN)
SegITK.CopyInformation(alignedNrd)
...
sitk.WriteImage(SegITK, nrd2niiPath)

```

---

<div class="post-metadata">

**Author:** ![dchen](https://discourse.itk.org/user_avatar/discourse.itk.org/dchen/32/34_2.png) [@dchen](https://discourse.itk.org/u/dchen)\
**Post date:** [August 4, 2021, 4:46pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/8 "2021-08-04T16:46:21Z")

</div>

It looks like you’re doing a binary threshold on alignedNrd, right?

If so, you should be able to do something like this:

```
SegBN = (alignedNrd > 0)

```

This does the same thing in SimpleITK, without having to go to NumPy.

---

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 4, 2021, 4:59pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/9 "2021-08-04T16:59:34Z")

</div>

This solution worked perfectly:

```auto
(array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]),
 array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]))

```

Also shows same properties in ITKsnap. Didn’t know ITKsnap changes the spacing for visualization.  
Thanks!

---

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 4, 2021, 10:15pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/10 "2021-08-04T22:15:48Z")

</div>

This also works perfectly.

```auto
>> imgnb.affine, segnb2.affine
(array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]),
 array([[-0.36132801, 0. , 0. , 69.19999695],
        [0. , -0.36132801, 0. , 109.80000305],
        [0. , 0. , 0.625 , -240.375],
        [0. , 0. , 0. , 1.]]))

```

Thanks!

---

<div class="post-metadata">

**Author:** ![banikr](https://discourse.itk.org/user_avatar/discourse.itk.org/banikr/32/3296_2.png) [@banikr](https://discourse.itk.org/u/banikr)\
**Post date:** [August 7, 2021, 9:18pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/11 "2021-08-07T21:18:45Z")

</div>

Hello @dzenanz  
When I try to write the Binary SegITK image as nifti file, I get the following error:

```auto
sitk.WriteImage(SegItk, nrd2niiPath)
  File "/home/banikr2/miniconda3/envs/carotid36/lib/python3.6/site-packages/SimpleITK/extra.py", line 394, in WriteImage
    return writer.Execute(image)
  File "/home/banikr2/miniconda3/envs/carotid36/lib/python3.6/site-packages/SimpleITK/SimpleITK.py", line 5518, in Execute
    return _SimpleITK.ImageFileWriter_Execute(self, *args)
TypeError: Wrong number or type of arguments for overloaded function 'ImageFileWriter_Execute'.
  Possible C/C++ prototypes are:
    itk::simple::ImageFileWriter::Execute(itk::simple::Image const &)
    itk::simple::ImageFileWriter::Execute(itk::simple::Image const &,std::string const &,bool,int)

```

Any idea how to solve it?

---

<div class="post-metadata">

**Author:** ![MRMR](https://discourse.itk.org/letter_avatar_proxy/v4/letter/m/f08c70/32.png) [@MRMR](https://discourse.itk.org/u/MRMR)\
**Post date:** [March 7, 2022, 3:52pm UTC](https://discourse.itk.org/t/dicom-nrrd-nifti-spacing-origin-mismatch/4311/12 "2022-03-07T15:52:30Z")

</div>

Hi @banikr,

I am struggling with the same point, can you share with me how did you managed to convert from dicom/nrrd to nifty keeping the origins matched?
