# How to manipulate DICOM tags on individual slices from python code

**URL:** https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481
**Category:** Uncategorized
**Tags:** dicom, python
**Created:** [October 6, 2021, 1:53pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481 "2021-10-06T13:53:22Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![br\_cpvc](https://discourse.itk.org/user_avatar/discourse.itk.org/br_cpvc/32/3078_2.png) [@br\_cpvc](https://discourse.itk.org/u/br_cpvc)
#### Post date: [October 6, 2021, 1:53pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/1 "2021-10-06T13:53:22Z")

</div>

I use the following code snippet for manipulating DICOM tags on individual slice:

```auto
...
    # insert tags per slice
    general_metadata = gdcmIO.GetMetaDataDictionary()

    metadata_array = []
    for slice_counter in range(1, num_slices):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.append(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)
...

```

The entire program can be seen in the bottom of the post if needed.

I however get the following error when executing my program:

```auto
Traceback (most recent call last):
  File "nifti2dicom.py", line 74, in <module>
    nifti_to_dicom(args.input_file, args.output_dir, args.output_prefix)
  File "nifti2dicom.py", line 61, in nifti_to_dicom
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)
TypeError: in method 'itkImageSeriesWriterIUS3IUS2_SetMetaDataDictionaryArray', argument 2 of type 'std::vector< itkMetaDataDictionary *,std::allocator< itkMetaDataDictionary * > > const *const'

```

I have tested many different ways of parsing the metadata\_array to the SetMetaDataDictionaryArray function but cannot seem to find the correct way of doing this.

Any help or pointer to information would be of great value.

The full program code for convert a nifti file to a DICOM Series:

```auto
# inspired by: https://itk.org/Doxygen50/html/Examples_2IO_2ImageReadDicomSeriesWrite_8cxx-example.html

import argparse
import os
import itk

def nifti_to_dicom(input_filename, output_dir, prefix):
    PixelType = itk.US
    Dimension = 3
    ReaderType = itk.Image[PixelType, Dimension]
    reader = itk.ImageSeriesReader[ReaderType].New()
    dicomIO = itk.NiftiImageIO.New()
    reader.SetImageIO(dicomIO)
    reader.SetFileName(input_filename)
    reader.Update()
    image = reader.GetOutput()

    region = image.GetLargestPossibleRegion()
    start = region.GetIndex()
    size = region.GetSize()

    namesGenerator = itk.NumericSeriesFileNames.New()
    format = output_dir + "/" + prefix + "%04d.dcm"
    namesGenerator.SetSeriesFormat(format)
    start_index = start[2] + 1
    namesGenerator.SetStartIndex(start_index)
    end_index = start_index + size[2] - 1
    namesGenerator.SetEndIndex(end_index)
    namesGenerator.SetIncrementIndex(1)

    OutputPixelType = itk.US
    OutputDimension = 2
    SeriesWriterType = itk.Image[OutputPixelType, OutputDimension]

    seriesWriter = itk.ImageSeriesWriter[ReaderType, SeriesWriterType].New()

    seriesWriter.SetInput(image)
    seriesWriter.SetFileNames(namesGenerator.GetFileNames())

    gdcmIO = itk.GDCMImageIO.New()
    # inspired by: https://itk.org/ITKExamples/src/IO/GDCM/ReadAndPrintDICOMTags/Documentation.html
    metadata = gdcmIO.GetMetaDataDictionary()
    slice_spacing = image.GetSpacing()[2]
    # format, removes 0 from e.g. 1.0 if it is 0
    metadata['0018|0050'] = '{0:g}'.format(slice_spacing)
    metadata['0008|0060'] = "MR"
    seriesWriter.SetImageIO(gdcmIO)

    # insert tags per slice
    # inspired by: https://itk.org/ITKExamples/src/IO/GDCM/ResampleDICOMSeries/Documentation.html
    num_slices = size[2]
    general_metadata = gdcmIO.GetMetaDataDictionary()

    metadata_array = []
    for slice_counter in range(1, num_slices):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.append(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

    os.makedirs(output_dir, exist_ok=True)
    seriesWriter.Update()

if __name__ == " __main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--input-file', required=True)
    parser.add_argument('-o', '--output-dir', required=True)
    parser.add_argument('-p', '--output-prefix', default="slice_")
    args = parser.parse_args()

    nifti_to_dicom(args.input_file, args.output_dir, args.output_prefix)

```

---

<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: [October 6, 2021, 2:10pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/2 "2021-10-06T14:10:00Z")

</div>

@matt.mccormick do we need any special handling of `DictionaryArrayType`? If not, what is the problem here?

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [October 27, 2021, 12:49pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/3 "2021-10-27T12:49:45Z")

</div>

@br_cpvc welcome to the ITK community! ☀

A quick note inspecting the code:

```auto
    PixelType = itk.US
    Dimension = 3
    ReaderType = itk.Image[PixelType, Dimension]
    reader = itk.ImageSeriesReader[ReaderType].New()
    dicomIO = itk.NiftiImageIO.New()
    reader.SetImageIO(dicomIO)
    reader.SetFileName(input_filename)
    reader.Update()
    image = reader.GetOutput()

```

could be just:

```auto
    image = itk.imread(input_filename)

```

> @matt.mccormick do we need any special handling of DictionaryArrayType? If not, what is the problem here?

Yes, we need to use the requested type here,

> argument 2 of type 'std::vector\< itkMetaDataDictionary

so instead of:

```auto
    metadata_array = []
    for slice_counter in range(1, num_slices):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.append(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

```

we create the `std::vector`:

```auto
    metadata_array = itk.vector[itk.MetaDataDictionary]()
    for slice_counter in range(1, num_slices):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.push_back(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

```

The `Array` name here is understandably misleading!

---

<div class="post-metadata">

### Author: ![br\_cpvc](https://discourse.itk.org/user_avatar/discourse.itk.org/br_cpvc/32/3078_2.png) [@br\_cpvc](https://discourse.itk.org/u/br_cpvc)
#### Post date: [October 28, 2021, 12:31pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/4 "2021-10-28T12:31:10Z")

</div>

@dzenanz thank you for forwarding my question to the right person

@matt.mccormick thank you for taking the time to answer my question, and giving me hints to improve my implementation.

```auto
I have tried changing the code as you suggest to:

    metadata_array = itk.vector[itk.MetaDataDictionary]()
    for slice_counter in range(1, num_slices):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.push_back(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

```

with these code changes I however get a “Segmentation fault (core dumped)” error message when executing, I don’t know how to debug or proceed, do you have suggestions?

when removing the line:

```auto
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

```

The “Segmentation fault (core dumped)” error goes away and output files are produced.

My setup: Popos 20.04 with itk installed using pip through conda. Have test with the following itk versions: 5.1.2, 5.2.0, 5.3rc1 but get the same results.

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [November 4, 2021, 1:50am UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/5 "2021-11-04T01:50:15Z")

</div>

@br_cpvc we may need to run in a Debug build of ITK to find the backtrace related to the error.

If an empty metadata dictionary is created per slice, does the segfault still occur?

> general\_metadata = gdcmIO.GetMetaDataDictionary()

It is likely that there are tags other than `0020|0013` that need to be set per-slice.

---

<div class="post-metadata">

### Author: ![blowekamp](https://discourse.itk.org/user_avatar/discourse.itk.org/blowekamp/32/79_2.png) [@blowekamp](https://discourse.itk.org/u/blowekamp)
#### Post date: [November 4, 2021, 12:33pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/6 "2021-11-04T12:33:42Z")

</div>

Looking at the [itk::ImageSeriesWrite](https://github.com/InsightSoftwareConsortium/ITK/blob/master/Modules/IO/ImageBase/include/itkImageSeriesWriter.hxx) does not do anything specific for DICOM files. It may be easier to write out the slices slice by slice yourself with the ImageFileWriter ( or procedural equivalent ).

---

<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: [November 4, 2021, 12:48pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/7 "2021-11-04T12:48:03Z")

</div>

Hello @br_cpvc,

Just adding to @blowekamp’s response, this [SimpleITK Example](https://simpleitk.readthedocs.io/en/master/link_DicomSeriesFromArray_docs.html) illustrates how to do what you want. I believe it is straightforward to translate it to ITK Python.

---

<div class="post-metadata">

### Author: ![br\_cpvc](https://discourse.itk.org/user_avatar/discourse.itk.org/br_cpvc/32/3078_2.png) [@br\_cpvc](https://discourse.itk.org/u/br_cpvc)
#### Post date: [November 4, 2021, 2:35pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/8 "2021-11-04T14:35:18Z")

</div>

@matt.mccormick I tried, as you suggested, to move the general\_metadata inside the for loop so that it is created per slice, like so:

```python
    metadata_array = itk.vector[itk.MetaDataDictionary]()
    for slice_counter in range(1, num_slices):
        general_metadata = gdcmIO.GetMetaDataDictionary()
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.push_back(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

```

this however do not change the output I get, it still reports “Segmentation fault (core dumped)” when I execute the code.

I have tried to build itk in debug mode to see how far I could get on my own. I have done the following until now:

```bash
sudo apt install -y git cmake python3.8-dev
git clone https://github.com/InsightSoftwareConsortium/ITK.git
cd ITK/
git checkout v5.2.1
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug -DITK_WRAP_PYTHON=ON ..
make -j 3

```

I think that I got ITK build correctly in debug mode, but are unsure how to proceed from here and execute my program so that I can inspect the debug output. If you have any pointers to some notes or documentation which could help me setup a debugging environment that would be of great help.

---

<div class="post-metadata">

### Author: ![br\_cpvc](https://discourse.itk.org/user_avatar/discourse.itk.org/br_cpvc/32/3078_2.png) [@br\_cpvc](https://discourse.itk.org/u/br_cpvc)
#### Post date: [November 4, 2021, 2:37pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/9 "2021-11-04T14:37:27Z")

</div>

Hi @blowekamp thank you for your input. I’m not entirely sure how the itk::ImageSeriesWriter works, but I’m trying to do the per slice python equivalent of what is implemented in: [https://github.com/biolab-unige/nifti2dicom/blob/master/src/core/n2dOutputExporter.cxx](https://github.com/biolab-unige/nifti2dicom/blob/master/src/core/n2dOutputExporter.cxx)

Hi @zivy thank you for you suggestion, I will take a look at the code and see if it is transferable.

---

<div class="post-metadata">

### Author: ![matt.mccormick](https://discourse.itk.org/user_avatar/discourse.itk.org/matt.mccormick/32/7_2.png) [@matt.mccormick](https://discourse.itk.org/u/matt.mccormick)
#### Post date: [November 11, 2021, 12:22am UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/10 "2021-11-11T00:22:44Z")

</div>

> [@br\_cpvc](#):
>
> I think that I got ITK build correctly in debug mode

@br_cpvc you got it 👏 👍

Create a symbolic link to the `WrapITK.pth` file in your build tree to a virtualenv `site-packages` to use the ITK Python build tree inside Python.

To find out where the issues is, you want to get a stack trace with `gdb`. Here is a [general guide for debugging CPython with GDB](https://wiki.python.org/moin/DebuggingWithGdb).

@brad-t-moore also has some great tips for debugging ITK Python.

---

<div class="post-metadata">

### Author: ![br\_cpvc](https://discourse.itk.org/user_avatar/discourse.itk.org/br_cpvc/32/3078_2.png) [@br\_cpvc](https://discourse.itk.org/u/br_cpvc)
#### Post date: [November 17, 2021, 12:38pm UTC](https://discourse.itk.org/t/how-to-manipulate-dicom-tags-on-individual-slices-from-python-code/4481/11 "2021-11-17T12:38:07Z")

</div>

@matt.mccormick thank you for the pointers, they were the last pieces of the puzzle that I needed to figure things out.

I did the following to get the debug build setup and running in a gdb environment:

```bash
pip install itk
mv ~/.local/lib/python3.8/site-packages/itk ~/.local/lib/python3.8/site-packages/itk_old
ln -s ~/ITK/build/Wrapping/Generators/Python/itk ~/.local/lib/python3.8/site-packages/itk

sudo apt-get install gdb python3.8-dbg

wget http://www.neuromorphometrics.com/1103_3.tgz
tar --extract -f 1103_3.tgz
gdb -ex r --args /usr/bin/python3 Tools/nifti2dicom.py -i Data/1103/3/NIFTI/1103_3.nii -o test -p test_prefix_

```

After a lot of debugging and trail/error coding I finally managed to figure out what was happening. I needed to change the code to the following to get the it working:

```python
    # list to store references to the itk.MetaDataDictionary objects
    # created inside the for loop, if the references are not stored
    # outside the for loop, then the objects' reference count returns
    # to zero when exiting the loop and the C++ objects are deleted,
    # if the objects are deleted before the function:
    # seriesWriter.Update() is called, then the entire application
    # exits with a segmentation fault.
    tmp_ref_list = []
    metadata_array = itk.vector[itk.MetaDataDictionary]()
    for slice_counter in range(1, num_slices + 1):
        slice_metadata = itk.MetaDataDictionary(general_metadata)
        # temporary work around, see comment above
        tmp_ref_list.append(slice_metadata)
        # instance number
        slice_metadata['0020|0013'] = slice_counter
        metadata_array.push_back(slice_metadata)
    seriesWriter.SetMetaDataDictionaryArray(metadata_array)

    os.makedirs(output_dir, exist_ok=True)
    seriesWriter.Update()

```

To avoid the segmentation fault (which was caused by deallocation of the itk.MetaDataDictionary objects stored inside the metadata\_array), I had to add local references for all the slice\_metadata objects created inside the for loop, and store these references until after the seriesWriter.Update() function has been called.

I’m unsure if this is an actually bug in the ITK python wrapper, or if this is how it is suppose to work. If it is an bug in ITK, I will gladly submit an bug issue upstream so that the problem can be addressed in a future version. What do you think, is this a bug?

I’m furthermore unsure if the work around that I have implemented is actually the correct/best way to do a work around, or if there are other/better ways of dealing with object references inside python?
