Sorting Images in DicomObjects is quite different in COM and .NET versions, due to the different structures of the collections which hold them.
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
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.
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.
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)