diff --git a/presidio-image-redactor/presidio_image_redactor/dicom_image_pii_verify_engine.py b/presidio-image-redactor/presidio_image_redactor/dicom_image_pii_verify_engine.py index ad95cb3f..f811319c 100644 --- a/presidio-image-redactor/presidio_image_redactor/dicom_image_pii_verify_engine.py +++ b/presidio-image-redactor/presidio_image_redactor/dicom_image_pii_verify_engine.py @@ -66,6 +66,11 @@ class DicomImagePiiVerifyEngine(ImagePiiVerifyEngine, DicomImageRedactorEngine): """ instance_copy = deepcopy(instance) + try: + instance_copy.PixelData + except AttributeError: + raise AttributeError("Provided DICOM instance lacks pixel data.") + # Load image for processing with tempfile.TemporaryDirectory() as tmpdirname: # Convert DICOM to PNG and add padding for OCR (during analysis) diff --git a/presidio-image-redactor/presidio_image_redactor/dicom_image_redactor_engine.py b/presidio-image-redactor/presidio_image_redactor/dicom_image_redactor_engine.py index 57cdb7db..c262313b 100644 --- a/presidio-image-redactor/presidio_image_redactor/dicom_image_redactor_engine.py +++ b/presidio-image-redactor/presidio_image_redactor/dicom_image_redactor_engine.py @@ -50,8 +50,13 @@ class DicomImageRedactorEngine(ImageRedactorEngine): :return: DICOM instance with redacted pixel data. """ # Check input - if type(image) != pydicom.dataset.FileDataset: + if type(image) not in [pydicom.dataset.FileDataset, pydicom.dataset.Dataset]: raise TypeError("The provided image must be a loaded DICOM instance.") + try: + image.PixelData + except AttributeError: + raise AttributeError("Provided DICOM instance lacks pixel data.") + instance = deepcopy(image) # Load image for processing @@ -771,6 +776,11 @@ class DicomImageRedactorEngine(ImageRedactorEngine): # Load instance instance = pydicom.dcmread(dst_path) + try: + instance.PixelData + except AttributeError: + raise AttributeError("Provided DICOM file lacks pixel data.") + # Load image for processing with tempfile.TemporaryDirectory() as tmpdirname: # Convert DICOM to PNG and add padding for OCR (during analysis) diff --git a/presidio-image-redactor/tests/test_data/0_ORIGINAL_no_pixels.dcm b/presidio-image-redactor/tests/test_data/0_ORIGINAL_no_pixels.dcm new file mode 100644 index 00000000..a1ae4d0a Binary files /dev/null and b/presidio-image-redactor/tests/test_data/0_ORIGINAL_no_pixels.dcm differ diff --git a/presidio-image-redactor/tests/test_dicom_image_pii_verify_engine.py b/presidio-image-redactor/tests/test_dicom_image_pii_verify_engine.py index 8a2eb64a..ccd5b16d 100644 --- a/presidio-image-redactor/tests/test_dicom_image_pii_verify_engine.py +++ b/presidio-image-redactor/tests/test_dicom_image_pii_verify_engine.py @@ -1,5 +1,6 @@ """Unit tests for dicom_image_pii_verify_engine """ +from copy import deepcopy import pydicom from presidio_image_redactor import ( @@ -121,6 +122,28 @@ def test_verify_dicom_instance_happy_path( assert mock_analyze.call_count == 1 assert mock_verify.call_count == 1 +def test_verify_dicom_instance_exception( + mock_engine: DicomImagePiiVerifyEngine, + get_mock_dicom_instance: pydicom.dataset.FileDataset, +): + """Test exceptions for DicomImagePiiVerifyEngine.verify_dicom_instance + Args: + mock_engine (DicomImagePiiVerifyEngine): Instantiated engine. + get_mock_dicom_instance (pydicom.dataset.FileDataset): Loaded DICOM. + """ + with pytest.raises(Exception) as exc_info: + # Arrange + padding_width = 25 + test_instance = deepcopy(get_mock_dicom_instance) + del test_instance.PixelData + expected_error_type = AttributeError + + # Act + _, _, _ = mock_engine.verify_dicom_instance(test_instance, padding_width) + + # Assert + assert expected_error_type == exc_info.typename + # ------------------------------------------------------ # DicomImagePiiVerifyEngine.eval_dicom_instance() diff --git a/presidio-image-redactor/tests/test_dicom_image_redactor_engine.py b/presidio-image-redactor/tests/test_dicom_image_redactor_engine.py index 7bea8fcb..3dc7acd4 100644 --- a/presidio-image-redactor/tests/test_dicom_image_redactor_engine.py +++ b/presidio-image-redactor/tests/test_dicom_image_redactor_engine.py @@ -41,6 +41,7 @@ def mock_engine(): Path(TEST_DICOM_PARENT_DIR), [ Path(TEST_DICOM_PARENT_DIR, "0_ORIGINAL.dcm"), + Path(TEST_DICOM_PARENT_DIR, "0_ORIGINAL_no_pixels.dcm"), Path(TEST_DICOM_PARENT_DIR, "RGB_ORIGINAL.dcm"), Path(TEST_DICOM_DIR_2, "1_ORIGINAL.DCM"), Path(TEST_DICOM_DIR_2, "2_ORIGINAL.dicom"), @@ -537,7 +538,7 @@ def test_add_padding_exceptions( "src_path, expected_num_of_files", [ (Path(TEST_DICOM_PARENT_DIR, "0_ORIGINAL.dcm"), 1), - (Path(TEST_DICOM_PARENT_DIR), 15), + (Path(TEST_DICOM_PARENT_DIR), 16), (Path(TEST_DICOM_DIR_1), 3), (Path(TEST_DICOM_DIR_2), 2), (Path(TEST_DICOM_DIR_3), 1), @@ -1120,7 +1121,8 @@ def test_DicomImageRedactorEngine_redact_happy_path( (Path(TEST_DICOM_PARENT_DIR), "TypeError"), ("path_here", "TypeError"), (np.random.randint(255, size=(64, 64)), "TypeError"), - (Image.fromarray(np.random.randint(255, size=(400, 400),dtype=np.uint8)), "TypeError") + (Image.fromarray(np.random.randint(255, size=(400, 400),dtype=np.uint8)), "TypeError"), + (pydicom.dcmread(Path(TEST_DICOM_PARENT_DIR, "0_ORIGINAL_no_pixels.dcm")), "AttributeError") ], ) def test_DicomImageRedactorEngine_redact_exceptions( @@ -1255,6 +1257,7 @@ def test_DicomImageRedactorEngine_redact_single_dicom_image_happy_path( [ (Path(TEST_DICOM_PARENT_DIR), "FileNotFoundError"), (Path("nonexistentfile.extension"), "FileNotFoundError"), + (Path(TEST_DICOM_PARENT_DIR, "0_ORIGINAL_no_pixels.dcm"), "AttributeError") ], ) def test_DicomImageRedactorEngine_redact_single_dicom_image_exceptions(