Sorting Images
Sorting Images in DicomObjects is quite different in COM and .NET versions, due to the different structures of the collections which hold them.
DicomObjects.NET
Sorting is actually trivial, as the DicomImageCollection is derived from the standard generic Collection, and has a constructor which accepts an IEnumerable
DicomImageCollection collection = new DicomImageCollection();
// read images into collection
collection = new DicomImageCollection(from image in collection orderby image.InstanceUID select image);
Or you could sort directly on the underlying List
For more details, see: Sorting Images in DicomObjects.NET
DicomObjects.COM
DicomImages and DicomDataSets collection objects have a move method which can be used to swap the indices of 2 images or datasets within the collection.
Important Note Do not confuse the Move method with C-Move.
So if for example you wish to order the images within your DicomViewer control by instance number(00020,0013) you could use the move method combined with a classic bubble sort.
e.g.
Dim i As Integer
Dim sw As Boolean
Dim im1 As DicomImage, im2 As DicomImage, p1 As Single, p2 As Single
Do 'for each series
sw = False
For i = 1 To Viewer.Images.Count - 1
set im1 = Viewer.Images(i)
set im2 = Viewer.Images(i + 1)
'you should trap errors here i.e. check that the attribute
'exists before reading the value.
p1 = im1.Attributes(&H20, &H13).Value
p2 = im2.Attributes(&H20, &H13).Value
If (p2 > p1) Then
sw = True
Viewer.Images.Move i, i + 1
End If
Next
Loop While sw
The result is that the images will be re-indexed according to Instance number. You could of course use this method to sort by alternative Dicom attributes.
Position Sorting
In fact, sorting by image number is a very bad idea (see my contributions to a thread on the UK radiologists discussion forum at http://www.pacsgroup.org.uk/forum/messages/2/9840.html), as different manufacturers may produce images in different orders, and it is better to sort by position, but this raises the question of how to know which of the position variables to use (there are 3 values in Image Position (patient) which is 0020,0032), so this short guide may help.
Look at first at the SIX values in 0020,0037 which are 2 x 3-element vectors defining the plane of the image (look in part 3 for the full definition) - they should be the same for all the images in a parallel set. You sort on the element from 0020,0032 which either 0 or closest to zero in each of those 2 vectors from 0020,0037.
So for instance (this is real MR data):
(0020,0032) 3 Image Position (Patient)
-80.587417980677 : -112.25763605359 : -37.861883640289
(0020,0037) 6 Image Orientation (Patient)
1 : -2.0510349e-010 : 0 : 2.051034897e-010 : 1 : 0
So the orientation vectors are
- 1 : -2.0510349e-010 : 0 (i.e. 1,0,0)
- 2.051034897e-010 : 1 : 0 (i.e. 0,1,0)
So the value which is 0 in both is the third one (Z), so you sort on the third value of 0020,0032, and as it is always defined in the same direction relative to the patient, you can use it for consistent sorting. Note that you may still need to consider the values of the vectors in 0020,0037 to make sure that your volume set is not a “mirror-image”.
Following is VB code demonstrating how to get the correct value on which to sort:
Dim im As DicomImage
Set im = DicomViewer1.CurrentImage
Dim x1, y1, z1, x2, y2, z2 As Double
x1 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(1))
y1 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(2))
z1 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(3))
x2 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(4))
y2 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(5))
z2 = CDbl(im.Attributes(&H20, &H37).ValueByIndex(6))
Dim v1, v2, v3 As Double
v1 = x1 * x1 + x2 * x2
v2 = y1 * y1 + y2 * y2
v3 = z1 * z1 + z2 * z2
Dim SortIndex As Integer ' determine which dimension to sort
If (v1 <= v2) And (v1 <= v3) Then
SortIndex = 1 ' Sort on X dimension
End If
If (v2 <= v1) And (v2 <= v3) Then
SortIndex = 2 ' Sort on Y dimension
End If
If (v3 <= v1) And (v3 <= v2) Then
SortIndex = 3 ' Sort on Z dimension
End If
Then use that value to determine the sort method as above, but replace two lines setting p1 & p2 in the original by these two:
p1 = im1.Attributes(&H20, &H32).ValueByIndex(SortIndex)
p2 = im2.Attributes(&H20, &H32).ValueByIndex(SortIndex)