Sorting dynamic studies in DICOM

I work with dynamic, or multi-frame, PET scans, so in essence 4-D datasets.  Nuclear medicine scans have frequently used file formats that are either proprietary or  used largely or wholly by NM scans.  These formats tend to support dynamic studies natively.  Newer PET scanners come with native DICOM capabilities, but older scanners and some research scanners use different file formats.  I’ve been trying to get everything into DICOM format, so it can all go into a PACS for storage and distribution.

One of the tricky steps is, getting your software to recognize the concept of a timeframe, or volume.  There are several DICOM header elements that could be used to group the slice files into frames, and different software interprets the headers differently.  I’m building DICOM headers from scratch for a scanner that creates ECAT format files, and this step is proving quite interesting, shall we say.

I started by looking at how a commercial system groups dynamic PET studies.  The example I’m using is a GE PET scanner which is acquiring 30 frames of 35 slices each, so it creates 1,050 DICOM files.  I notice that while Vinci shows the 30×35 arrangement, the Osirix viewer and DCM4CHEE PACS server both show the study as a single frame of 1050 files.

So how are they being grouped?  I have a small perl utility program I use to show differing fields between two DICOM files.  I rename the DICOM files when I receive them from the PACS, since we use a wide range of research software, very little of which is PACS- or even DICOM-aware.  So for much of our research needs, we just treat the DICOM files as image files, and number them from 1 to 1050.

First, I compare two adjacent slices from the same frame.

[widget dynamicpet] 115% 0001.dcm 0002.dcm | grep -v UID
0008 0013  InstanceCreationTime: 122044.000               122045.000
0020 0013           ImageNumber: 1                        2
0020 0032  ImagePositionPatient: 128128                1281284.25
0020 1041         SliceLocation: 0.00000000000000         4.25000000000000
0028 1053          RescaleSlope: 0.20659                  0.106116
0054 1330            ImageIndex: 1                        2
Nothing unexpected here, the image number and index are sequential and the image position increments by the thickness of one slice.  I do note though that InstanceCreationTime is the time of reconstruction, so is not going to be useful to tell one frame from another.  RescaleSlope differs from slice to slice – with the very wide range of values in a PET scan, it’s customary to scale each slice separately.

Next, I look at the difference between the same slice in two consecutive frames: files 001 and 036 hold slice 1 from frames 1 and 2.

[Note: I'm numbering the frames and slices from 1.  My background is CS so all experience and intuition says I should count from 0, and some software does just this, but I find that counting from 1 confuses fewer people than counting from 0.]

[widget dynamicpet] 117% 0001.dcm 0036.dcm | grep -v UID
0008 0013  InstanceCreationTime: 122044.000          122059.000
0008 0033             ImageTime: 110638.00           110419.00
0020 0013           ImageNumber: 1                   36
0028 1053          RescaleSlope: 0.20659             1.62858
0054 1300    FrameReferenceTime: 0                   15000
0054 1321           DecayFactor: 1.00427             1.01288
0054 1324        DeadTimeFactor: 1.61667             2.54626
0054 1330            ImageIndex: 1                   36

Well we have another time field differing, ImageTime, but it’s not related to the frame time because this scan started at 08:34.  ImageNumber and ImageIndex both are counting the file number rather than slice number.  The key field that differs here is (0054,1300) FrameReferenceTime, which is listing the frame start offset in milliseconds.  This field is part of the NM multi-frame module so is present only in NM scans.