Skip to content
Matthew Brett edited this page Nov 22, 2012 · 12 revisions

BIAP4 - merging nibabel and dcmstack

In which we set out what dcmstack does and how it might integrate with the nibabel objects and functions.

This first draft is my (MBs) understanding of what Brendan Moloney told me today (21 Nov 2012).

Overview

dcmstack reads a series of DICOM images, works out their relationship in terms of slices and volumes, and compiles them into nifti volumes.

In the course of the read, dcmstack creates a DcmMetaExtension object : https://github.com/moloney/dcmstack/blob/master/src/dcmstack/dcmmeta.py#L92

The DcmMetaExtension contains copied, summarized or inferred information from reading the slice by slice or volume DICOM information from the DICOM headers.

As one or more DICOMs are read, the DcmMetaExtension fills out its fields.

Some fields in the DcmMetaExtension are identified as being per-slice, others as being per-volume.

After reading the information into the DcmMetaExtension, dcmstack gets the pixel data, and affine, and compiles that into a Nifti image, with the DcmMetaExtension as a header extension.

When working with these images, it's attractive to be able to keep track of the meta-information in the DcmMetaExtension. For example, when taking slice out of a 3D volume, we want to keep track of the information specific to the chosen slice, and remove information for other slices.

At the moment, dcmstack only creates Nifti images. There's no reason that this should be so, and the relationship of dcmstack to Nifti should be more flexible.

Issues

DcmMetaExtension tied to NiftiExtension

At the moment, DcmMetaExtension inherits from the NiftiExtension, allowing the data to be dumped out to JSON when writing into the extension part of a Nifti header.

There's no reason that the DcmMetaExtension should be tied to the Nifti format.

Plan

Refactor DcmMetaExtension to inherit from object. Maybe rename DcmMeta or something. Make a NiftiExtension object when needed by with a new object wrapping the DcmMeta in the Extension API?

Keeping track of metadata when manipulating images

When slicing images, it is good to be able to keep track of the relevant DICOM metadata for the particular slice. Or when merging images, it is good go be able to compile the metadata across slices into the (e.g) volume metadata. Or, say, when coregistering an image, it is good to be able to rewrite the metadata to point out that the slice times or positions may have been changed by the coregistration.

At the moment, dcmstack deals with this by wrapping the image with DICOM meta information in NiftiWrapper object : see https://github.com/moloney/dcmstack/blob/master/src/dcmstack/dcmmeta.py#L1185 . This object accepts a Nifti image as input, that usually contains a DcmMetaExtension, and has methods get_meta (to get metadata from extension), split (for taking slice specific metadata into the split parts), meta_valid to check the metadata against the Nifti information, and methods to remove / replace the extension, save to a filename, and create the object with various alternative classmethod constructors.

In particular, the meta_valid method needs to know about both the enclosed image, and the enclosed meta data.

Can we put this stuff into the SpatialImage image object of nibabel, so we don't need this wrapper object?

Plan

Put the DcmMeta data into the extra object that is input to the SpatialImage and all other nibabel image types.

Add a get_meta method to SpatialImage that uses the to-be-defined API of the extra object. Maybe, by default, this would just get keys out of the mapping.

Define an API for the extra object to give back metadata for slices.

Use this API to get slices. Try and make this work with functions outside the SpatialImage such as four_to_three and three_to_four in nibabel.funcs. These functions could use the extra API to get slice meta-information.

** TODO : specific proposal for SpatialImage and extra API changes **

Detecting slice or volume-specific data difficult for 3D and 4D DICOMS

The DcmMeta object needs to be able to identify slice and volume specific information when reading the DICOM, so that it can correctly split the resulting metadata, or merge it.

This is easy for slice-by-slice DICOM files because anything that differs between the slices is by definition slice-specific. For 3D and 4D data, such as Siemens Mosaic, some of the fields in the private headers contains slice-by-slice information for the volume contained. There's not automatic way of detecting slice-by-slice information in this case, so we have to specify which fields are slice-by-slice when reading. That is, we need to specialize the DICOM read for each type of volume-containing DICOM - such as Mosaic or the Philips multi format (?).

Plan

Add create_dcmmeta method to the nibabel DICOM wrapper objects, that can be specialized for each known DICOM format variation. Put the rules for slice information etc into each class.

Clone this wiki locally