# Squeeze dicom ITK image from 4D to 3D

**URL:** https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300
**Category:** Uncategorized
**Created:** [July 28, 2021, 5:34pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300 "2021-07-28T17:34:42Z")
**Posts on this page:** 5
**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: [July 28, 2021, 5:34pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300/1 "2021-07-28T17:34:42Z")

</div>

I have Dicom images in an unusual format. For example, usually, Dicom images are saved in a casepath/folder in multiple slices.  
`IM-0001-0240-0001.dcm`  
I use the following helper function to read the dicom images:

```auto
def dicomread(casePath, imgitk=None):
    """
    casePath: the folder location where all the dicom slices are in a subject/case
              e.g. r'E:\CAP Exam Data\Images\SPH-0706\66154284\20627700'
    return: 3D Image in numpy format and all image informations
    """
    if not os.path.isdir(casePath):
        print("The path doesn't exist.")
    reader = sitk.ImageSeriesReader()
    dicom_names = reader.GetGDCMSeriesFileNames(casePath)
    reader.SetFileNames(dicom_names)
    image = reader.Execute()
    image_array = sitk.GetArrayFromImage(image) # z, y, x
    origin = image.GetOrigin() # x, y, z
    spacing = image.GetSpacing() # x, y, z
    size = image.GetSize()
    direction = image.GetDirection() # image
    data_type = image.GetPixelIDTypeAsString()
    if imgitk == True:
        return image
    else:
        return image_array, origin, spacing, size, direction, data_type

```

For one image like I mentioned I get 4 dimensions instead of 3.

```auto
>> dcmItk = dicomread(r'/media/banikr/Elucid_data/dicoms', True)
>> dcmItk.GetSize()
(512, 512, 480, 1)

```

Is it possible to squeeze the itk image and use the 3D output in all itk operations?  
For example, I use resample to align masks on 3D ITK images.

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [July 29, 2021, 9:00pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300/2 "2021-07-29T21:00:35Z")

</div>

Hello @banikr,  
This should do the trick inside your function (using SimpleITK\>=2.1.0):

```auto
image = reader.Execute()
if image.GetDimension()==4 and image.GetSize()[3]==1:
  image = image[...,0]

```

---

<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: [July 29, 2021, 9:51pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300/3 "2021-07-29T21:51:12Z")

</div>

This actually worked. Thanks for the hint.

```auto
def dicomread(casePath, imgitk=None):
    """
    casePath: the folder location where all the dicom slices are in a subject/case
              e.g. r'E:\Elucid_data\CAP Exam Data\Images\SPH-0706\66154284\20627700'
    return: 3D Image in numpy format and all image informations
    """
    if not os.path.isdir(casePath):
        print("The path doesn't exist.")
    reader = sitk.ImageSeriesReader()
    dicom_names = reader.GetGDCMSeriesFileNames(casePath)
    reader.SetFileNames(dicom_names)
    image = reader.Execute() # type --> 'SimpleITK.SimpleITK.Image'
    if image.GetDimension() == 4 and image.GetSize()[3] == 1:
        image = sitk.GetArrayFromImage(image)[0,...]
        image = sitk.GetImageFromArray(image) # type --> 'SimpleITK.SimpleITK.Image'
    image_array = sitk.GetArrayFromImage(image) # z, y, x
    origin = image.GetOrigin() # x, y, z
    spacing = image.GetSpacing() # x, y, z
    size = image.GetSize()
    direction = image.GetDirection() # image
    data_type = image.GetPixelIDTypeAsString()
    if imgitk == True:
        return image
    else:
        return image_array, origin, spacing, size, direction, data_type

```

---

<div class="post-metadata">

### Author: ![zivy](https://discourse.itk.org/user_avatar/discourse.itk.org/zivy/32/1726_2.png) [@zivy](https://discourse.itk.org/u/zivy)
#### Post date: [July 30, 2021, 12:51pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300/4 "2021-07-30T12:51:10Z")

</div>

Hello @banikr,

Your new code has a bug, the `image` lost its spatial information (spacing/origin/direction matrix) in the transition to numpy and back to SimpleITK. If you don’t want to upgrade to SimpleITK 2.1.0 for the new syntax you can use the old one, both retain the spatial information:

```auto
image = reader.Execute()
if image.GetDimension()==4 and image.GetSize()[3]==1:
  image = image[:,:,:,0]

```

---

<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: [July 30, 2021, 4:53pm UTC](https://discourse.itk.org/t/squeeze-dicom-itk-image-from-4d-to-3d/4300/5 "2021-07-30T16:53:02Z")

</div>

I didn’t notice that! Thanks for the catch. I think removing the `sitk.Get..` modules works without any issues.

```auto
def dicomread(casePath, imgitk=None):
    """
    casePath: the folder location where all the dicom slices are in a subject/case
              e.g. r'E:\Elucid_data\CAP Exam Data\Images\SPH-0706\66154284\20627700'
              also works for casepath will only one .dcm extension with 4D size.
    return: 3D Image in numpy format and all image informations
    """
    if not os.path.isdir(casePath):
        print("The path doesn't exist.")
    reader = sitk.ImageSeriesReader()
    dicom_names = reader.GetGDCMSeriesFileNames(casePath)
    reader.SetFileNames(dicom_names)
    image = reader.Execute() # type --> 'SimpleITK.SimpleITK.Image'
    if image.GetDimension() == 4 and image.GetSize()[3] == 1:
# image = sitk.GetArrayFromImage(image)[0,...]
        image = image[:,:,:,0]
# image = sitk.GetImageFromArray(image) # type --> 'SimpleITK.SimpleITK.Image'
    if imgitk == True:
        return image
    else:
        image_array = sitk.GetArrayFromImage(image) # z, y, x
        origin = image.GetOrigin() # x, y, z
        spacing = image.GetSpacing() # x, y, z
        size = image.GetSize()
        direction = image.GetDirection() # image
        data_type = image.GetPixelIDTypeAsString()
        return image_array, origin, spacing, size, direction, data_type

```

The function results:

```auto
>> new_img = dicomread(dcmPath, True)
>> new_img.GetSize()

(512, 512, 240)

```

One other minor thing I noticed:  
`image = image[:,:,:,0]` indexing works but `image = image[...,0]` generates `IndexError: invalid index`. Maybe due to data structure in ITK vs numpy or so.
