@@ -23,9 +23,11 @@ private class DICOMSliceFile
23
23
{
24
24
public AcrNemaFile file ;
25
25
public float location = 0 ;
26
+ public Vector3 position = Vector3 . zero ;
26
27
public float intercept = 0.0f ;
27
28
public float slope = 1.0f ;
28
29
public float pixelSpacing = 0.0f ;
30
+ public bool missingLocation = false ;
29
31
}
30
32
31
33
private IEnumerable < string > fileCandidates ;
@@ -53,12 +55,21 @@ public override VolumeDataset Import()
53
55
}
54
56
55
57
List < DICOMSliceFile > files = new List < DICOMSliceFile > ( ) ;
58
+ bool needsCalcLoc = false ;
56
59
foreach ( string filePath in fileCandidates )
57
60
{
58
61
DICOMSliceFile sliceFile = ReadDICOMFile ( filePath ) ;
59
62
if ( sliceFile != null )
63
+ {
64
+ needsCalcLoc |= sliceFile . missingLocation ;
60
65
files . Add ( sliceFile ) ;
66
+ }
61
67
}
68
+
69
+ // Calculate slice location from "Image Position" (0020,0032)
70
+ if ( needsCalcLoc )
71
+ CalcSliceLocFromPos ( files ) ;
72
+
62
73
// Sort files by slice location
63
74
files . Sort ( ( DICOMSliceFile a , DICOMSliceFile b ) => { return a . location . CompareTo ( b . location ) ; } ) ;
64
75
@@ -125,38 +136,55 @@ private DICOMSliceFile ReadDICOMFile(string filePath)
125
136
{
126
137
DICOMSliceFile slice = new DICOMSliceFile ( ) ;
127
138
slice . file = file ;
128
- // Read location
139
+
129
140
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)
130
147
if ( file . DataSet . Contains ( locTag ) )
131
148
{
132
149
DataElement elemLoc = file . DataSet [ locTag ] ;
133
150
slice . location = ( float ) Convert . ToDouble ( elemLoc . Value [ 0 ] ) ;
134
151
}
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
+ }
135
163
else
136
164
{
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") ;
138
166
return null ;
139
167
}
168
+
140
169
// Read intercept
141
- Tag interceptTag = new Tag ( "(0028,1052)" ) ;
142
170
if ( file . DataSet . Contains ( interceptTag ) )
143
171
{
144
172
DataElement elemIntercept = file . DataSet [ interceptTag ] ;
145
173
slice . intercept = ( float ) Convert . ToDouble ( elemIntercept . Value [ 0 ] ) ;
146
174
}
147
175
else
148
176
Debug . LogWarning ( $ "The file { filePath } is missing the intercept element. As a result, the default transfer function might not look good.") ;
177
+
149
178
// Read slope
150
- Tag slopeTag = new Tag ( "(0028,1053)" ) ;
151
179
if ( file . DataSet . Contains ( slopeTag ) )
152
180
{
153
181
DataElement elemSlope = file . DataSet [ slopeTag ] ;
154
182
slice . slope = ( float ) Convert . ToDouble ( elemSlope . Value [ 0 ] ) ;
155
183
}
156
184
else
157
185
Debug . LogWarning ( $ "The file { filePath } is missing the intercept element. As a result, the default transfer function might not look good.") ;
186
+
158
187
// Read pixel spacing
159
- Tag pixelSpacingTag = new Tag ( "(0028,0030)" ) ;
160
188
if ( file . DataSet . Contains ( pixelSpacingTag ) )
161
189
{
162
190
DataElement elemPixelSpacing = file . DataSet [ pixelSpacingTag ] ;
@@ -247,5 +275,22 @@ private static int[] ToPixelArray(PixelData pixelData)
247
275
return null ;
248
276
}
249
277
}
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
+ }
250
295
}
251
296
}
0 commit comments