I’m using SimpleITK’s DICOMOrient
to reorient a stack of DICOM slices. When I read files as a simple list (instead of using ImageSeriesReader
), SITK only uses the first slice’s Origin/Spacing and infers the rest on the fly. In my case, the series was in LPS– (Z positions ran from –180 to –60), but because the first slice had Z = –60, SITK assumed subsequent slices must increase in Z (LPS+) and reordered them incorrectly. Switching to ImageSeriesReader.GetGDCMSeriesFileNames(...)
fixes orientation automatically.
Are there other edge cases or pitfalls of DICOMOrient
on DICOM series that I might be unaware of and should watch out for?
blowekamp
(Bradley Lowekamp)
June 5, 2025, 12:38pm
2
Hello,
Are you able to share your DICOM series?
There are 3 steps here to look at:
input list to the ImageSeriesReader
the meta-data of the read image e.g. Direciton cosine matrix, Origin and Spacing
the DICOMOrient behavior
I am not sure what you mean by “read files as a simple list”, and how that compares to the list generated by GetGDCMSeriesFileNames
. The series reader does not reorder the list, is uses what is provided, so the difference between these approaches likely originates here.
The following issue and PR seem related:
opened 10:15AM - 14 May 25 UTC
Bug Report
**Describe the bug**
I have the a series comprising 413 dicom slices the "Image… PositionPatient" tag for the slices are :
slice 1 : -216.500 \ -216.500 \ 70.000
slice 2: -216.500 \ -216.500 \ 68.750
.....
slice 413 : -216.500 \ -216.500 \ -445.000
The "ImageOrientation" is the same for all tags :
(0020,0037) Image Orientation Patient 1.000000\0.000000\0.000000\0.000000\1.000000\0.000000
I read these slices with the Image Series Reader:
```
reader = sitk.ImageSeriesReader()
reader.SetFileNames(dcm_list)
image = reader.Execute()
```
Reading the slice from the last to the first (bottom to top), the metadata of the final 3d image is inconsistant with the values of the dicom tags :
image.GetOrigin() -> (-216.5, -216.5, -445.0) seems OK
image.GetDirection() -> (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0) not OK last vector should be 1 instead of -1
if I put the slices from the first to the last I get correct results :
image.GetOrigin() ->(-216.5, -216.5, 70.0) seems OK
image.GetDirection() -> (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0) now it is OK since we are reading from top to bottom
so depending on the order of the slice given, one give a coherent result in term of metadata and the other does not.
My understanding was that the code computed the 3d direction matrix with both the "image orientation" for the first two axes, and the vector defined by the vector separing the "image position patient" of the two first slice given. In that case it should be 0 / 0 / 1 when reading the image from bottom to top and 0 / 0 / -1 from top to bottom but last vector is always 0 / 0 / -1
**To Reproduce**
Hard to reproduce without sharing the dcm files itself, on request it can be done
Thanks !
Here are the full information of the final 3d image for reference :
```
Image (0x40bcd700)
RTTI typeinfo: itk::Image<int, 3u>
Reference Count: 1
Modified Time: 16338
Debug: Off
Object Name:
Observers:
none
Source: (none)
Source output name: (none)
Release Data: Off
Data Released: False
Global Release Data: Off
PipelineMTime: 1807
UpdateMTime: 16334
RealTimeStamp: 0 seconds
LargestPossibleRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [512, 512, 413]
BufferedRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [512, 512, 413]
RequestedRegion:
Dimension: 3
Index: [0, 0, 0]
Size: [512, 512, 413]
Spacing: [0.845703, 0.845703, 1.25]
Origin: [-216.5, -216.5, -445]
Direction:
1 0 0
0 1 0
0 0 -1
IndexToPointMatrix:
0.845703 0 0
0 0.845703 0
0 0 -1.25
PointToIndexMatrix:
1.18245 0 0
0 1.18245 0
0 0 -0.8
Inverse Direction:
1 0 0
0 1 0
0 0 -1
PixelContainer:
ImportImageContainer (0x40f65de0)
RTTI typeinfo: itk::ImportImageContainer<unsigned long, int>
Reference Count: 1
Modified Time: 1875
Debug: Off
Object Name:
Observers:
none
Pointer: 0x7fdb14418010
Container manages memory: true
Size: 108265472
Capacity: 108265472
```
master
← blowekamp:dicom_series_reverse
opened 08:38PM - 20 May 25 UTC
If the spacing between slices is negative, then direction cosine matrix was not … correct with reguards to the sign.
## PR Checklist
- [ ] No [API changes](https://github.com/InsightSoftwareConsortium/ITK/blob/master/CONTRIBUTING.md#breaking-changes) were made (or the changes have been approved)
- [ ] No [major design changes](https://github.com/InsightSoftwareConsortium/ITK/blob/master/CONTRIBUTING.md#design-changes) were made (or the changes have been approved)
- [ ] Added test (or behavior not changed)
- [ ] Updated API documentation (or API not changed)
- [ ] Added [license](https://github.com/InsightSoftwareConsortium/ITK/blob/master/Utilities/KWStyle/ITKHeader.h) to new files (if any)
- [ ] Added Python wrapping to new files (if any) as described in [ITK Software Guide](https://itk.org/ItkSoftwareGuide.pdf) Section 9.5
- [ ] Added [ITK examples](https://github.com/InsightSoftwareConsortium/ITKSphinxExamples) for all new major features (if any)
Refer to the [ITK Software Guide](https://itk.org/ItkSoftwareGuide.pdf) for
further development details if necessary.
1 Like
As it turns out sorted(glob.glob('*.dcm'))
is definitely not good enough. Switching to sitk.ImageSeriesReader.GetGDCMSeriesFileNames
as a source for sitk.ImageSeriesReader().SetFileNames(files_list)
fixed the issue.
Thank you for the assistance!
2 Likes