comparison OrthancStone/Sources/Toolbox/DicomInstanceParameters.cpp @ 1746:4bedae500652

Automatically compute SliceThickness from GridFrameOffsetVector when SliceThickness is not present in the DICOM tags
author Benjamin Golinvaux <bgo@osimis.io>
date Fri, 12 Feb 2021 10:41:17 +0100
parents 9ac2a65d4172
children 5f74ebe2516b
comparison
equal deleted inserted replaced
1745:04019fd631aa 1746:4bedae500652
46 46
47 if (dicom.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false)) 47 if (dicom.LookupStringValue(increment, Orthanc::DICOM_TAG_FRAME_INCREMENT_POINTER, false))
48 { 48 {
49 Orthanc::Toolbox::ToUpperCase(increment); 49 Orthanc::Toolbox::ToUpperCase(increment);
50 50
51 // This is the "Grid Frame Offset Vector" tag (DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) 51 // We only support volumes where the FrameIncrementPointer (0028,0009) (required) contains
52 // the "Grid Frame Offset Vector" tag (DICOM_TAG_GRID_FRAME_OFFSET_VECTOR)
52 if (increment != "3004,000C") 53 if (increment != "3004,000C")
53 { 54 {
54 LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image"; 55 LOG(WARNING) << "Bad value for the FrameIncrementPointer tags in a multiframe image";
55 target.resize(0); 56 target.resize(0);
56 return; 57 return;
58 } 59 }
59 60
60 if (!LinearAlgebra::ParseVector(target, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) || 61 if (!LinearAlgebra::ParseVector(target, dicom, Orthanc::DICOM_TAG_GRID_FRAME_OFFSET_VECTOR) ||
61 target.size() != numberOfFrames) 62 target.size() != numberOfFrames)
62 { 63 {
63 LOG(INFO) << "The frame offset information is missing in a multiframe image"; 64 LOG(ERROR) << "The frame offset information (GridFrameOffsetVector (3004,000C)) is missing in a multiframe image";
64 65
65 // DO NOT use ".clear()" here, as the "Vector" class doesn't behave like std::vector! 66 // DO NOT use ".clear()" here, as the "Vector" class doesn't behave like std::vector!
66 target.resize(0); 67 target.resize(0);
67 } 68 }
68 } 69 }
107 !dicom.GetValue(Orthanc::DICOM_TAG_ROWS).ParseFirstUnsignedInteger(height_)) 108 !dicom.GetValue(Orthanc::DICOM_TAG_ROWS).ParseFirstUnsignedInteger(height_))
108 { 109 {
109 height_ = 0; 110 height_ = 0;
110 } 111 }
111 112
113
114 bool sliceThicknessPresent = true;
112 if (!dicom.ParseDouble(sliceThickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS)) 115 if (!dicom.ParseDouble(sliceThickness_, Orthanc::DICOM_TAG_SLICE_THICKNESS))
113 { 116 {
117 LOG(INFO) << "The (non-madatory) slice thickness information is missing in a multiframe image";
114 sliceThickness_ = 100.0 * std::numeric_limits<double>::epsilon(); 118 sliceThickness_ = 100.0 * std::numeric_limits<double>::epsilon();
119 sliceThicknessPresent = false;
115 } 120 }
116 121
117 GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom); 122 GeometryToolbox::GetPixelSpacing(pixelSpacingX_, pixelSpacingY_, dicom);
118 123
119 std::string position, orientation; 124 std::string position, orientation;
125 130
126 // Must be AFTER setting "numberOfFrames_" 131 // Must be AFTER setting "numberOfFrames_"
127 if (numberOfFrames_ > 1) 132 if (numberOfFrames_ > 1)
128 { 133 {
129 ExtractFrameOffsets(frameOffsets_, dicom, numberOfFrames_); 134 ExtractFrameOffsets(frameOffsets_, dicom, numberOfFrames_);
135
136 // if the slice thickness is unknown, we try to infer it from the sequence of grid frame offsets
137 // this only works if:
138 // - the first offset is 0.0 (case (a) of http://dicom.nema.org/medical/Dicom/2017c/output/chtml/part03/sect_C.8.8.3.2.html)
139 // - the offsets are all equal, to some small tolerance
140 // - the offsets is positive (increasing throughout the frames)
141 if (!sliceThicknessPresent)
142 {
143 if (frameOffsets_.size() >= 2)
144 {
145 double sliceThickness = frameOffsets_[1] - frameOffsets_[0];
146 bool sameSized = true;
147 if (sliceThickness > 0)
148 {
149 for (size_t i = 2; i < frameOffsets_.size(); ++i)
150 {
151 double currentThickness = frameOffsets_[i] - frameOffsets_[i-1];
152 if (!LinearAlgebra::IsNear(sliceThickness, currentThickness))
153 {
154 LOG(ERROR) << "Unable to extract slice thickness from GridFrameOffsetVector (3004,000C) (reason: varying spacing)";
155 sameSized = false;
156 break;
157 }
158 }
159 if (sameSized)
160 {
161 sliceThickness_ = sliceThickness;
162 LOG(INFO) << "SliceThickness was not specified in the Dicom but was inferred from GridFrameOffsetVector (3004,000C).";
163 }
164 }
165 }
166 else
167 {
168 LOG(ERROR) << "Unable to extract slice thickness from GridFrameOffsetVector (3004,000C) (reason: GridFrameOffsetVector not present or too small)";
169 }
170 }
130 } 171 }
131 else 172 else
132 { 173 {
133 frameOffsets_.resize(0); 174 frameOffsets_.resize(0);
134 } 175 }