Skip to content

Commit f83623f

Browse files
committed
fix(data): warn when PydicomReader falls back to identity affine
PydicomReader._get_affine silently returned an identity matrix when the ImageOrientationPatient (0020,0037) and ImagePositionPatient (0020,0032) tags were absent (e.g. some multi-frame Enhanced DICOM), leaving the image orientation and spacing wrong with no indication. Emit a UserWarning naming the missing tags and recommending ITKReader for such files; the fallback behaviour is otherwise unchanged. Fixes #8468. Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>
1 parent b7d14c8 commit f83623f

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

monai/data/image_reader.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,14 @@ def _get_affine(self, metadata: dict, lps_to_ras: bool = True):
738738
"""
739739
affine: np.ndarray = np.eye(4)
740740
if not ("00200037" in metadata and "00200032" in metadata):
741+
warnings.warn(
742+
"PydicomReader: ImageOrientationPatient (0020,0037) and/or "
743+
"ImagePositionPatient (0020,0032) tags are missing, so the affine "
744+
"matrix cannot be derived and defaults to the identity. The image "
745+
"orientation and spacing may be incorrect (e.g. for multi-frame "
746+
"Enhanced DICOM); consider using ITKReader for such files.",
747+
stacklevel=2,
748+
)
741749
return affine
742750
# "00200037" is the tag of `ImageOrientationPatient`
743751
rx, ry, rz, cx, cy, cz = metadata["00200037"]["Value"]

tests/data/test_pydicom_reader.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright (c) MONAI Consortium
2+
# Licensed under the Apache License, Version 2.0 (the "License");
3+
# you may not use this file except in compliance with the License.
4+
# You may obtain a copy of the License at
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
# Unless required by applicable law or agreed to in writing, software
7+
# distributed under the License is distributed on an "AS IS" BASIS,
8+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9+
# See the License for the specific language governing permissions and
10+
# limitations under the License.
11+
12+
from __future__ import annotations
13+
14+
import unittest
15+
16+
import numpy as np
17+
18+
from monai.data import PydicomReader
19+
from tests.test_utils import SkipIfNoModule
20+
21+
22+
@SkipIfNoModule("pydicom")
23+
class TestPydicomReaderAffine(unittest.TestCase):
24+
def test_missing_orientation_tags_warns_and_returns_identity(self):
25+
# Without ImageOrientationPatient (0020,0037) and ImagePositionPatient
26+
# (0020,0032) the affine cannot be derived. The reader falls back to the
27+
# identity matrix; regression test for #8468 ensures this is no longer
28+
# silent so users know orientation/spacing may be wrong.
29+
reader = PydicomReader()
30+
with self.assertWarns(UserWarning):
31+
affine = reader._get_affine({})
32+
np.testing.assert_array_equal(affine, np.eye(4))
33+
34+
def test_partial_orientation_tags_warns(self):
35+
# Only one of the two required tags present is still insufficient.
36+
reader = PydicomReader()
37+
metadata = {"00200037": {"Value": [1, 0, 0, 0, 1, 0]}} # orientation only
38+
with self.assertWarns(UserWarning):
39+
affine = reader._get_affine(metadata)
40+
np.testing.assert_array_equal(affine, np.eye(4))
41+
42+
43+
if __name__ == "__main__":
44+
unittest.main()

0 commit comments

Comments
 (0)