Skip to content

Commit aa72d45

Browse files
committed
issue-26: Calculate slice location from Image Position (0020,0032) if there is no location tag.
1 parent 8692f0c commit aa72d45

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

Assets/Scripts/Importing/DICOMImporter.cs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ private class DICOMSliceFile
2323
{
2424
public AcrNemaFile file;
2525
public float location = 0;
26+
public Vector3 position = Vector3.zero;
2627
public float intercept = 0.0f;
2728
public float slope = 1.0f;
2829
public float pixelSpacing = 0.0f;
30+
public bool missingLocation = false;
2931
}
3032

3133
private IEnumerable<string> fileCandidates;
@@ -53,12 +55,21 @@ public override VolumeDataset Import()
5355
}
5456

5557
List<DICOMSliceFile> files = new List<DICOMSliceFile>();
58+
bool needsCalcLoc = false;
5659
foreach (string filePath in fileCandidates)
5760
{
5861
DICOMSliceFile sliceFile = ReadDICOMFile(filePath);
5962
if(sliceFile != null)
63+
{
64+
needsCalcLoc |= sliceFile.missingLocation;
6065
files.Add(sliceFile);
66+
}
6167
}
68+
69+
// Calculate slice location from "Image Position" (0020,0032)
70+
if (needsCalcLoc)
71+
CalcSliceLocFromPos(files);
72+
6273
// Sort files by slice location
6374
files.Sort((DICOMSliceFile a, DICOMSliceFile b) => { return a.location.CompareTo(b.location); });
6475

@@ -125,38 +136,55 @@ private DICOMSliceFile ReadDICOMFile(string filePath)
125136
{
126137
DICOMSliceFile slice = new DICOMSliceFile();
127138
slice.file = file;
128-
// Read location
139+
129140
Tag locTag = new Tag("(0020,1041)");
141+
Tag posTag = new Tag("(0020,0032)");
142+
Tag interceptTag = new Tag("(0028,1052)");
143+
Tag slopeTag = new Tag("(0028,1053)");
144+
Tag pixelSpacingTag = new Tag("(0028,0030)");
145+
146+
// Read location (optional)
130147
if (file.DataSet.Contains(locTag))
131148
{
132149
DataElement elemLoc = file.DataSet[locTag];
133150
slice.location = (float)Convert.ToDouble(elemLoc.Value[0]);
134151
}
152+
// If no location tag, read position tag (will need to calculate location afterwards)
153+
else if (file.DataSet.Contains(posTag))
154+
{
155+
DataElement elemLoc = file.DataSet[posTag];
156+
Vector3 pos = Vector3.zero;
157+
pos.x = (float)Convert.ToDouble(elemLoc.Value[0]);
158+
pos.y = (float)Convert.ToDouble(elemLoc.Value[1]);
159+
pos.z = (float)Convert.ToDouble(elemLoc.Value[2]);
160+
slice.position = pos;
161+
slice.missingLocation = true;
162+
}
135163
else
136164
{
137-
Debug.LogError($"Missing location tag in file: {filePath}.\n The file will not be imported");
165+
Debug.LogError($"Missing location/position tag in file: {filePath}.\n The file will not be imported");
138166
return null;
139167
}
168+
140169
// Read intercept
141-
Tag interceptTag = new Tag("(0028,1052)");
142170
if (file.DataSet.Contains(interceptTag))
143171
{
144172
DataElement elemIntercept = file.DataSet[interceptTag];
145173
slice.intercept = (float)Convert.ToDouble(elemIntercept.Value[0]);
146174
}
147175
else
148176
Debug.LogWarning($"The file {filePath} is missing the intercept element. As a result, the default transfer function might not look good.");
177+
149178
// Read slope
150-
Tag slopeTag = new Tag("(0028,1053)");
151179
if (file.DataSet.Contains(slopeTag))
152180
{
153181
DataElement elemSlope = file.DataSet[slopeTag];
154182
slice.slope = (float)Convert.ToDouble(elemSlope.Value[0]);
155183
}
156184
else
157185
Debug.LogWarning($"The file {filePath} is missing the intercept element. As a result, the default transfer function might not look good.");
186+
158187
// Read pixel spacing
159-
Tag pixelSpacingTag = new Tag("(0028,0030)");
160188
if (file.DataSet.Contains(pixelSpacingTag))
161189
{
162190
DataElement elemPixelSpacing = file.DataSet[pixelSpacingTag];
@@ -247,5 +275,22 @@ private static int[] ToPixelArray(PixelData pixelData)
247275
return null;
248276
}
249277
}
278+
279+
private void CalcSliceLocFromPos(List<DICOMSliceFile> slices)
280+
{
281+
// We use the first slice as a starting point (a), andthe normalised vector (v) between the first and second slice as a direction.
282+
Vector3 v = (slices[1].position - slices[0].position).normalized;
283+
Vector3 a = slices[0].position;
284+
slices[0].location = 0.0f;
285+
286+
for(int i = 1; i < slices.Count; i++)
287+
{
288+
// Calculate the vector between a and p (ap) and dot it with v to get the distance along the v vector (distance when projected onto v)
289+
Vector3 p = slices[i].position;
290+
Vector3 ap = p - a;
291+
float dot = Vector3.Dot(ap, v);
292+
slices[i].location = dot;
293+
}
294+
}
250295
}
251296
}

0 commit comments

Comments
 (0)