Repository: Project-MONAI/MONAI

Issue:
Wrong spacing checking logic in DICOM series combination
**Describe the bug**

I found some issues in the following code snip:

https://github.com/Project-MONAI/MONAI/blob/2cbed6cfa7a007fa8853a7bd8cf09303172686c9/monai/data/image_reader.py#L510-L521

1. In line 520, spacing should be got from `slices[idx]` instead of `first_slice`; there's the same issue in line 521;
2. the default value in line 514 is `[1.0, 1.0, 1.0]`, which is a `list` instance, while the default value in line 520 is `(1.0, 1.0, 1.0)`, which is a `tuple` instance, and `(1.0, 1.0, 1.0) == [1.0, 1.0, 1.0]` will result in `False`.

Wrong spacing checking logic in DICOM series combination
**Describe the bug**

I found some issues in the following code snip:

https://github.com/Project-MONAI/MONAI/blob/2cbed6cfa7a007fa8853a7bd8cf09303172686c9/monai/data/image_reader.py#L510-L521

1. In line 520, spacing should be got from `slices[idx]` instead of `first_slice`; there's the same issue in line 521;
2. the default value in line 514 is `[1.0, 1.0, 1.0]`, which is a `list` instance, while the default value in line 520 is `(1.0, 1.0, 1.0)`, which is a `tuple` instance, and `(1.0, 1.0, 1.0) == [1.0, 1.0, 1.0]` will result in `False`.



Discussion:
thanks for reporting, would you like to submit a PR to fix it? I think the relevant elementwise checks could be done with allclose https://github.com/Project-MONAI/MONAI/blob/2cbed6cfa7a007fa8853a7bd8cf09303172686c9/monai/transforms/utils_pytorch_numpy_unification.py#L58
Hi, I can make a PR later.
thanks for reporting, would you like to submit a PR to fix it? I think the relevant elementwise checks could be done with allclose https://github.com/Project-MONAI/MONAI/blob/2cbed6cfa7a007fa8853a7bd8cf09303172686c9/monai/transforms/utils_pytorch_numpy_unification.py#L58
Hi, I can make a PR later.

Resolving patch:
diff --git a/monai/data/image_reader.py b/monai/data/image_reader.py
--- a/monai/data/image_reader.py
+++ b/monai/data/image_reader.py
@@ -218,7 +218,7 @@ def read(self, data: Sequence[PathLike] | PathLike, **kwargs):
             data: file name or a list of file names to read,
             kwargs: additional args for `itk.imread` API, will override `self.kwargs` for existing keys.
                 More details about available args:
-                https://github.com/InsightSoftwareConsortium/ITK/blob/master/Wrapping/Generators/Python/itkExtras.py
+                https://github.com/InsightSoftwareConsortium/ITK/blob/master/Wrapping/Generators/Python/itk/support/extras.py
 
         """
         img_ = []
@@ -230,7 +230,7 @@ def read(self, data: Sequence[PathLike] | PathLike, **kwargs):
             name = f"{name}"
             if Path(name).is_dir():
                 # read DICOM series
-                # https://itk.org/ITKExamples/src/IO/GDCM/ReadDICOMSeriesAndWrite3DImage
+                # https://examples.itk.org/src/io/gdcm/readdicomseriesandwrite3dimage/documentation
                 names_generator = itk.GDCMSeriesFileNames.New()
                 names_generator.SetUseSeriesDetails(True)
                 names_generator.AddSeriesRestriction("0008|0021")  # Series Date
@@ -512,19 +512,19 @@ def _combine_dicom_series(self, data: Iterable):
         first_array = self._get_array_data(first_slice)
         shape = first_array.shape
         spacing = getattr(first_slice, "PixelSpacing", [1.0, 1.0, 1.0])
-        pos = getattr(first_slice, "ImagePositionPatient", (0.0, 0.0, 0.0))[2]
+        prev_pos = getattr(first_slice, "ImagePositionPatient", (0.0, 0.0, 0.0))[2]
         stack_array = [first_array]
         for idx in range(1, len(slices)):
             slc_array = self._get_array_data(slices[idx])
             slc_shape = slc_array.shape
-            slc_spacing = getattr(first_slice, "PixelSpacing", (1.0, 1.0, 1.0))
-            slc_pos = getattr(first_slice, "ImagePositionPatient", (0.0, 0.0, float(idx)))[2]
-            if spacing != slc_spacing:
+            slc_spacing = getattr(slices[idx], "PixelSpacing", (1.0, 1.0, 1.0))
+            slc_pos = getattr(slices[idx], "ImagePositionPatient", (0.0, 0.0, float(idx)))[2]
+            if not np.allclose(slc_spacing, spacing):
                 warnings.warn(f"the list contains slices that have different spacings {spacing} and {slc_spacing}.")
             if shape != slc_shape:
                 warnings.warn(f"the list contains slices that have different shapes {shape} and {slc_shape}.")
-            average_distance += abs(pos - slc_pos)
-            pos = slc_pos
+            average_distance += abs(prev_pos - slc_pos)
+            prev_pos = slc_pos
             stack_array.append(slc_array)
 
         if len(slices) > 1:


Test patch: