Medical Imaging Interaction Toolkit  2024.06.00
Medical Imaging Interaction Toolkit
MITK DICOM testing

Introduction

Reading DICOM data into mitk::Images is a complicated business since DICOM and MITK have very different ideas of images.

DICOMITKSeriesGDCMReader (formerly: DicomSeriesReader) brings DICOM and MITK as close together as possible by offering methods to load DICOM CT and MR images into mitk::Images, optionally grouping slices to 3D+t images.

Since there are so many possible sources for mistakes with any change to this loading process, testing the many assumptions implemented in DICOMITKSeriesGDCMReader is worthwhile. This document describes what and how these kind of tests are implemented.

Problem description

The task of loading DICOM files into mitk::Images is a challenge because of major differences in the way that DICOM and MITK represent images:

  • DICOM images
    • are mostly stored as one slice per file
    • do not describe how they can be arranged into image stacks with orthogonal axis
    • sometimes they cannot be arranged in image stacks as described above (e.g. tilted gantry)
  • mitk::Image (at least its mature areas)
    • represents image stacks with orthogonal axis (nothing like a tilted gantry)
    • have a concept of a fourth dimension (time steps)

Because image processing applications based on MITK still need a way to load DICOM images into mitk::Image objects, MITK needs a way to build image stacks and this needs to be well tested.

For more background information, see David Clunie's most valuable posts on comp.protocols.dicom, e.g.:

Test principle

The general idea for DICOM loaing tests is to run a set of known DICOM files through DICOMITKSeriesGDCMReader's methods GetSeries() and LoadDicomSeries() to generate mitk::Images. These images are then compared to expected image properties, such as the number of individual mitk::Images, positions, orientations, spacings, etc.

Stored expectations look like this (should be self-explanatory):

-- Image 1
Pixeltype: s
BitsPerPixel: 16
Dimension: 4
Dimensions: 64 64 6 1
Geometry:
  Matrix: 5.25 0 0 0 5.2468 0.139598 0 -0.183222 3.99757
  Offset: -159.672 -309.974 -69.0122
  Center: 0 0 0
  Translation: -159.672 -309.974 -69.0122
  Scale: 1 1 1
  Origin: -159.672 -309.974 -69.0122
  Spacing: 5.25 5.25 4
  TimeBounds: 0 1

-- Image 2
Pixeltype: s
BitsPerPixel: 16
Dimension: 4
Dimensions: 64 64 41 1
Geometry:
  Matrix: 5.25 0 0 0 5.25 0 0 0 4
  Offset: -160.672 -311.672 -285
  Center: 0 0 0
  Translation: -160.672 -311.672 -285
  Scale: 1 1 1
  Origin: -160.672 -311.672 -285
  Spacing: 5.25 5.25 4
  TimeBounds: 0 1

Implementation

Test helpers (applications and classes)

Application DumpDICOMMitkImage

Takes a list of DICOM images, loads them using TestDICOMLoading, then dumps information about the resulting mitk::Images to standard output.

This application is helpful when defining reference data for tests.

Application VerifyDICOMMitkImageDump

Takes a list of DICOM images and loads them using TestDICOMLoading. Takes a dump file as generated by DumpDICOMMitkImage, parses it and compares it to actually generated mitk::Images.

This application is used to implement the majority of test cases. They all load images, then verify the expected result structure.

Class TestDICOMLoading

Test case implementation

Individual test cases are stored in the MITK-Data repository and constructed by Core/Code/Testing/DICOMTesting/Testing/CMakeLists.txt

The CMake file parses given directories for subdirectories containing specific test cases. Each directory contains two files:

  • File "input": lists DICOM files that should be loaded for this test case
  • File "expected.dump": contains the image properties in the above mentioned dump format

Each test case is translated into a CTest test which evaluates the return value of a call to VerifyDICOMMitkImageDump.

Implemented test cases

From test set TinyCTAbdomen (see description.txt in this directory for details on test images):

  • singleslice : just a single slice (should work and contain meaningful spacing)
  • two_slices : two slices, spacing should be calculated correctly
  • all : load a "normal" series as a single 3D block
  • 3D_and_T : load a small set of slices with multiple time-steps
  • diff_orientation : load a set of files containing two differently oriented image blocks; at least two images (110,111) have minor errors in small decimal digits
  • diff_orientation_gaps : load a set of files containing two differently oriented image blocks, each missing slices, so blocks must be split
  • diff_spacing : load a set of files containing two set of slices with different spacings
  • gap : load slices that cannot form a single 3D block, because single slices are missing
  • gaps : slices missing in different locations, so multiple splits needed
  • unsorted_gaps : as before, just file names are unsorted
  • single_negative_spacing : from reported bug related to single MR images with misleading spacing information
  • tilted_gantry : slice origins do not align along first slice normal (happens with tilted gantries)
  • interleaved : two volumes of slices with origins along the same line. The volumes' slices interleave in their border region. This test is meant to correctly sort apart the two blocks instead of generating many two-slices groups in the interleaved region.
  • CR-MONO1-10-chest-spacing-none : CR image without spacing information - (1.0, 1.0) should be assumed
  • CR-MONO1-10-chest-spacing-pixelspacing : CR image with only "Pixel Spacing" tag - this should be used as spacing
  • CR-MONO1-10-chest-spacing-imagerpixelspacing : CR image with only "Imager Pixel Spacing" tag - this should be used as spacing
  • CR-MONO1-10-chest-spacing-calibrated : CR image with BOTH "Imager Pixel Spacing" and "Pixel Spacing" defined - "Pixel Spacing" should be used
  • OT-MONO2-8-colon : Secondary Capture image with gray value pixels - should be loaded
  • OT-PAL-8-face : Secondary Capture image with PALETTE pixel values - can be loaded, but display is not correct yet

From test set TiltHead (see description.txt in this directory for details on test images):

  • head_ct_tilt : load a series with gantry tilt and check its orientation

Specific other tests

This list is meant to provide an up-to-date list of all implemented DICOM loading tests. If you ever find this outdated, please update it or make the persons who invalidated the list update it.

mitkDICOMTestingSanityTest_* These tests implement basic testing of the implemented helper classes. The tests use DICOMITKSeriesGDCMReader to load a number of DICOM image. They verify:

  • DICOMITKSeriesGDCMReader recognizes all input files as DICOM images
  • DICOMITKSeriesGDCMReader generates a number of mitk::Images from the DICOM images
  • the number of mitk::Images matches a number given on the command line or CTest's add_test()
  • helper methods in class TestDICOMLoading make minimal sense (comparison of an image dump to itself must be valid)