Skip to content

Commit c740e36

Browse files
committed
Address concerns that the rescaled pixel array from DICOM is of type float64.
In the last version, rescale slope and intercept values were tried to cast to the smallest can_cast Nunpy type. Using pydicom apply_rescale loses this as it returns float64 if rescale slope and intercept are applied. So, enhancing the code will test for equivalence before "unsafely" casting the data. This will NOT reduce the mem usage of this operator as a new array will be created by casting from float64, and there is a small overhead for the checks. However, there are cases where downstream custom operators may save memory footprint. Signed-off-by: M Q <[email protected]>
1 parent 55148bd commit c740e36

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

monai/deploy/operators/dicom_series_to_volume_operator.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,17 +158,21 @@ def generate_voxel_data(self, series):
158158
f"Cannot process pixel data with Photometric Interpretation of {photometric_interpretation}."
159159
)
160160

161-
# NumPy's np.can_cast function, as of version 2.0, no longer supports Python scalars directly and
162-
# does not apply value-based logic for 0-D arrays and NumPy scalars.
163-
# The following can_cast calls are expecting the array is already of the correct type.
164-
if vol_data.dtype == np.uint8:
165-
logging.info("Rescaled pixel data is of type uint8.")
166-
elif np.can_cast(vol_data, np.uint16, casting="safe"):
167-
logging.info("Casting to uint16")
168-
vol_data = vol_data.astype(dtype=np.uint16, casting="safe")
169-
elif np.can_cast(vol_data, np.float32, casting="safe"):
170-
logging.info("Casting to float32")
171-
vol_data = vol_data.astype(dtype=np.float32, casting="safe")
161+
# The following tests are expecting the array is already of the Numpy type.
162+
if vol_data.dtype == np.uint8 or vol_data.dtype == np.uint16:
163+
logging.info("Rescaled pixel array is alrady of type uint8 or uint16.")
164+
# Check if casting to uint16 and back to float results in the same values.
165+
elif np.all(vol_data > 0) and np.array_equal(vol_data, vol_data.astype(np.uint16)):
166+
logging.info("Rescaled pixel array can be safely cast to uint16 with equivalence test.")
167+
vol_data = vol_data.astype(dtype=np.uint16)
168+
# Check if casting to int16 and back to float results in the same values.
169+
elif np.array_equal(vol_data, vol_data.astype(np.int16)):
170+
logging.info("Rescaled pixel array can be safely cast to int16 with equivalence test.")
171+
vol_data = vol_data.astype(dtype=np.int16)
172+
# Check casting to float32 with equivalence test
173+
elif np.array_equal(vol_data, vol_data.astype(np.float32)):
174+
logging.info("Rescaled pixel array can be cast to float32 with equivalence test.")
175+
vol_data = vol_data.astype(np.float32)
172176
else:
173177
logging.info("Rescaled pixel data remains as of type float64.")
174178

0 commit comments

Comments
 (0)