pyushkevich / itksnap

ITK-SNAP medical image segmentation tool
http://www.itksnap.org
GNU General Public License v3.0
299 stars 88 forks source link

Add workaround to load malformed 4D CTA DICOM files #128

Open a-a-danilov opened 6 months ago

a-a-danilov commented 6 months ago

We have several datasets with poorly formatted DICOM images. These datasets come from the same source and have the same problem. The first file in the series slightly differs in several DICOM tags from the rest files. Here is an example of differences between first and second files:

--- a/10000710.txt
+++ b/10000716.txt
@@ -9 +9 @@
-(0002,0003) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.1] #  60, 1 MediaStorageSOPInstanceUID
+(0002,0003) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.2] #  60, 1 MediaStorageSOPInstanceUID
@@ -21 +21 @@
-(0008,0018) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.1] #  60, 1 SOPInstanceUID
+(0008,0018) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.2] #  60, 1 SOPInstanceUID
@@ -110 +110 @@
-(0018,0050) DS [0.625000]                               #   8, 1 SliceThickness
+(0018,0050) DS [0.625]                                  #   6, 1 SliceThickness
@@ -112 +112 @@
-(0018,0088) DS [0.625000]                               #   8, 1 SpacingBetweenSlices
+(0018,0088) DS [0.625]                                  #   6, 1 SpacingBetweenSlices
@@ -118 +118 @@
-(0018,1100) DS [250.000000]                             #  10, 1 ReconstructionDiameter
+(0018,1100) DS [250]                                    #   4, 1 ReconstructionDiameter
@@ -121 +121 @@
-(0018,1120) DS [0.000000]                               #   8, 1 GantryDetectorTilt
+(0018,1120) DS [0]                                      #   2, 1 GantryDetectorTilt
@@ -162,3 +162,3 @@
-(0020,0013) IS [1]                                      #   2, 1 InstanceNumber
-(0020,0032) DS [-70.657\-205.374\-128.217]              #  26, 3 ImagePositionPatient
-(0020,0037) DS [1.000000\0.000000\0.000000\0.000000\1.000000\0.000000] #  54, 6 ImageOrientationPatient
+(0020,0013) IS [2]                                      #   2, 1 InstanceNumber
+(0020,0032) DS [-70.657\-205.374\-128.842]              #  26, 3 ImagePositionPatient
+(0020,0037) DS [1\0\0\0\1\0]                            #  12, 6 ImageOrientationPatient
@@ -167 +167 @@
-(0020,1041) DS [-128.2175]                              #  10, 1 SliceLocation
+(0020,1041) DS [-128.8425]                              #  10, 1 SliceLocation
@@ -187 +187 @@
-(0027,1044) FL -128.217499                              #   4, 1 Unknown Tag & Data
+(0027,1044) FL -128.842499                              #   4, 1 Unknown Tag & Data
@@ -206 +206 @@
-(0028,1053) DS [1.0]                                    #   4, 1 RescaleSlope
+(0028,1053) DS [1]                                      #   2, 1 RescaleSlope

The difference between the second file and the third file is quite small:

--- a/10000716.txt
+++ b/1000071A.txt
@@ -9 +9 @@
-(0002,0003) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.2] #  60, 1 MediaStorageSOPInstanceUID
+(0002,0003) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.3] #  60, 1 MediaStorageSOPInstanceUID
@@ -21 +21 @@
-(0008,0018) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.2] #  60, 1 SOPInstanceUID
+(0008,0018) UI [1.2.840.113619.2.416.3162372656626051609821512650571013401.3] #  60, 1 SOPInstanceUID
@@ -162,2 +162,2 @@
-(0020,0013) IS [2]                                      #   2, 1 InstanceNumber
-(0020,0032) DS [-70.657\-205.374\-128.842]              #  26, 3 ImagePositionPatient
+(0020,0013) IS [3]                                      #   2, 1 InstanceNumber
+(0020,0032) DS [-70.657\-205.374\-129.467]              #  26, 3 ImagePositionPatient
@@ -167 +167 @@
-(0020,1041) DS [-128.8425]                              #  10, 1 SliceLocation
+(0020,1041) DS [-129.4675]                              #  10, 1 SliceLocation
@@ -187 +187 @@
-(0027,1044) FL -128.842499                              #   4, 1 Unknown Tag & Data
+(0027,1044) FL -129.467499                              #   4, 1 Unknown Tag & Data

As you can see, the main difference is the addition of trailing zeros only in the first file in the following tags: SliceThickness, SpacingBetweenSlices, ReconstructionDiameter, GantryDetectorTilt, ImageOrientationPatient and RescaleSlope.

Since ITK-SNAP uses tag SliceThickness for computation of unique ID for image series, the whole dataset is split in two parts: the first sole file, and all remaining files. This behavior is acceptable when we work with a static 3D image, we can ignore the first slice and just work with slightly shorter image. However, it is impossible to open 4D images, since the first missing slice breaks the dimensions. A possible workaround is to manually delete all first slices from all time frames, which is not very user-friendly and quite tedious.

I propose to add several workarounds to allow loading of such malformed 4D CTA DICOM files. At first, we remove the trailing zeros from fractional part of SliceThickness tag, thus combining all files in one dataset. Next, we add a fallback sorting to MFOrderByIPPStrategy in case IPPSorter fails. The last change is needed since IPPSorter will fail if Gantry/Detector Tilt tag is not unique, resulting in wrong orientation of the first frame in the dynamic dataset.