def test_anonymise_directory(tmp_path): temp_filepath = tmp_path / "test.dcm" temp_anon_filepath = label_dicom_filepath_as_anonymised(temp_filepath) try: copyfile(TEST_FILEPATH, temp_filepath) assert not is_anonymised_directory(tmp_path) # Test file deletion anonymise_directory( tmp_path, delete_original_files=False, anonymise_filenames=False ) # # File should be anonymised but not dir, since original file # # is still present. assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) assert not is_anonymised_directory(tmp_path) remove_file(temp_anon_filepath) anonymise_directory( tmp_path, delete_original_files=True, anonymise_filenames=False ) # # File and dir should be anonymised since original file should # # have been deleted. assert is_anonymised_file(temp_anon_filepath) assert not exists(temp_filepath) assert is_anonymised_directory(tmp_path) finally: remove_file(temp_anon_filepath)
def _test_pseudonymise_cli_for_file(tmp_path, test_file_path): temp_filepath = pjoin(tmp_path, "test.dcm") try: logging.info("CLI test on %s", test_file_path) copyfile(test_file_path, temp_filepath) # Basic file pseudonymisation # Initially, just make sure it exits with zero and doesn't fail to generate output assert not is_anonymised_file(temp_filepath) # need the SOP Instance UID and SOP Class name to figure out the destination file name # but will also be using the dataset to do some comparisons. ds_input: pydicom.FileDataset = pydicom.dcmread(temp_filepath, force=True) pseudo_sop_instance_uid = pseudonymisation_api.pseudonymisation_dispatch[ "UI"](ds_input.SOPInstanceUID) sop_class_uid: pydicom.dataelem.DataElement = ds_input.SOPClassUID mode_prefix = DICOM_SOP_CLASS_NAMES_MODE_PREFIXES[ sop_class_uid.name # pylint: disable = no-member ] temp_anon_filepath = pjoin( tmp_path, "{}.{}_Anonymised.dcm".format(mode_prefix, pseudo_sop_instance_uid), ) assert not exists(temp_anon_filepath) anon_file_command = "pymedphys --verbose experimental dicom anonymise --pseudo".split( ) + [temp_filepath] logging.info("Command line: %s", anon_file_command) try: subprocess.check_call(anon_file_command) assert exists(temp_anon_filepath) # assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) ds_pseudo = pydicom.dcmread(temp_anon_filepath, force=True) assert ds_input["PatientID"].value != ds_pseudo["PatientID"].value finally: remove_file(temp_anon_filepath) # Basic dir anonymisation assert not is_anonymised_directory(tmp_path) assert not exists(temp_anon_filepath) anon_dir_command = "pymedphys --verbose experimental dicom anonymise --pseudo".split( ) + [str(tmp_path)] try: subprocess.check_call(anon_dir_command) # assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) finally: remove_file(temp_anon_filepath) finally: remove_file(temp_filepath)
def test_anonymise_file(): assert not is_anonymised_file(TEST_FILEPATH) temp_basename = "{}_{}.dcm".format(".".join(TEST_FILEPATH.split(".")[:-1]), uuid4()) temp_filepath = pjoin(dirname(TEST_FILEPATH), temp_basename) anon_private_filepath = "" anon_filepath_orig = "" anon_filepath_pres = "" try: # Private tag handling anon_private_filepath = anonymise_file(TEST_FILEPATH, delete_private_tags=False) assert not is_anonymised_file(anon_private_filepath, ignore_private_tags=False) assert is_anonymised_file(anon_private_filepath, ignore_private_tags=True) anon_private_filepath = anonymise_file(TEST_FILEPATH, delete_private_tags=True) assert is_anonymised_file(anon_private_filepath, ignore_private_tags=False) # Filename is anonymised? assert basename(anon_private_filepath) == TEST_ANON_BASENAME # Deletion of original file copyfile(TEST_FILEPATH, temp_filepath) anon_filepath_orig = anonymise_file(temp_filepath, delete_original_file=True) assert is_anonymised_file(anon_filepath_orig) assert not exists(temp_filepath) # Preservation of filename if desired expected_filepath = "{}_Anonymised.dcm".format(".".join( TEST_FILEPATH.split(".")[:-1])) anon_filepath_pres = anonymise_file(TEST_FILEPATH, anonymise_filename=False) assert anon_filepath_pres == expected_filepath finally: remove_file(temp_filepath) remove_file(anon_private_filepath) remove_file(anon_filepath_orig) remove_file(anon_filepath_pres)
def _check_is_anonymised_dataset_file_and_dir( ds, tmp_path, anon_is_expected=True, ignore_private_tags=False ): temp_filepath = str(tmp_path / "test.dcm") try: create.set_default_transfer_syntax(ds) ds.file_meta = TEST_FILE_META ds.save_as(temp_filepath, write_like_original=False) if anon_is_expected: assert is_anonymised_dataset(ds, ignore_private_tags) assert is_anonymised_file(temp_filepath, ignore_private_tags) assert is_anonymised_directory(tmp_path, ignore_private_tags) else: assert not is_anonymised_dataset(ds, ignore_private_tags) assert not is_anonymised_file(temp_filepath, ignore_private_tags) assert not is_anonymised_directory(tmp_path, ignore_private_tags) finally: remove_file(temp_filepath)
def test_alternative_identifying_keywords(): alternative_keyword_list = copy.copy(get_default_identifying_keywords()) alternative_keyword_list.append("SOPInstanceUID") test_file_path = get_treatment_record_test_file_path() ds_test = pydicom.dcmread(test_file_path, force=True) with tempfile.TemporaryDirectory() as output_directory: anon_private_filepath = anonymise_file( test_file_path, output_filepath=output_directory, delete_private_tags=True, identifying_keywords=alternative_keyword_list, ) ds_anon = pydicom.dcmread(anon_private_filepath, force=True) assert is_anonymised_file(anon_private_filepath, ignore_private_tags=False) assert ds_test["SOPInstanceUID"].value != ds_anon["SOPInstanceUID"].value
def _test_pseudonymise_file_at_path( test_file_path, test_identifying_keywords=None, test_replacement_strategy=None ): assert not is_anonymised_file(test_file_path) if test_identifying_keywords is None: identifying_keywords_for_pseudo = ( pseudonymisation_api.get_default_pseudonymisation_keywords() ) logging.info("Using pseudonymisation keywords") else: identifying_keywords_for_pseudo = test_identifying_keywords if test_replacement_strategy is None: replacement_strategy = pseudonymisation_api.pseudonymisation_dispatch logging.info("Using pseudonymisation strategy") else: replacement_strategy = test_replacement_strategy with tempfile.TemporaryDirectory() as output_directory: pseudonymised_file_path = anonymise_file( dicom_filepath=test_file_path, output_filepath=output_directory, delete_original_file=False, anonymise_filename=True, replace_values=True, # keywords_to_leave_unchanged=None, delete_private_tags=True, delete_unknown_tags=True, replacement_strategy=replacement_strategy, identifying_keywords=identifying_keywords_for_pseudo, ) # debug print + Assert to force the print # print("Pseudonymised file at: ", pseudonymised_file_path) # assert False assert exists(pseudonymised_file_path) ds_input = pydicom.dcmread(test_file_path, force=True) ds_pseudo = pydicom.dcmread(pseudonymised_file_path, force=True) # simplistic stand-in to make sure *something* is happening assert ds_input["PatientID"].value != ds_pseudo["PatientID"].value # make sure that we are not accidentally using the hardcode replacement approach assert ds_pseudo["PatientID"].value not in ["", "Anonymous"]
def test_anonymise_cli(tmp_path): temp_filepath = str(tmp_path / "test.dcm") try: copyfile(TEST_FILEPATH, temp_filepath) temp_anon_filepath = str(tmp_path / TEST_ANON_BASENAME) # Basic file anonymisation assert not is_anonymised_file(temp_filepath) assert not exists(temp_anon_filepath) anon_file_command = "pymedphys dicom anonymise".split() + [temp_filepath] try: subprocess.check_call(anon_file_command) assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) finally: remove_file(temp_anon_filepath) # File anonymisation - preserve filenames assert not is_anonymised_file(temp_filepath) expected_anon_filepath = label_dicom_filepath_as_anonymised(temp_filepath) assert not exists(expected_anon_filepath) anon_file_pres_command = "pymedphys dicom anonymise -f".split() + [ temp_filepath ] try: subprocess.check_call(anon_file_pres_command) assert is_anonymised_file(expected_anon_filepath) assert exists(temp_filepath) finally: remove_file(expected_anon_filepath) # File anonymisation - clear values assert not is_anonymised_file(temp_filepath) assert not exists(temp_anon_filepath) temp_cleared_anon_filepath = str(tmp_path / TEST_ANON_BASENAME) anon_file_clear_command = "pymedphys dicom anonymise -c".split() + [ temp_filepath ] try: subprocess.check_call(anon_file_clear_command) assert is_anonymised_file(temp_cleared_anon_filepath) assert pydicom.dcmread(temp_cleared_anon_filepath).PatientName == "" assert exists(temp_filepath) finally: remove_file(temp_cleared_anon_filepath) # File anonymisation - leave keywords unchanged assert not is_anonymised_file(temp_filepath) assert not exists(temp_anon_filepath) anon_file_keep_command = ( "pymedphys dicom anonymise".split() + [temp_filepath] + "-k PatientName".split() ) try: subprocess.check_call(anon_file_keep_command) assert not is_anonymised_file(temp_anon_filepath) ds = pydicom.dcmread(temp_anon_filepath) ds.PatientName = "Anonymous" assert is_anonymised_dataset(ds) assert exists(temp_filepath) finally: remove_file(temp_anon_filepath) # File anonymisation - private tag handling assert not is_anonymised_file(temp_filepath) assert not exists(temp_anon_filepath) anon_file_private_command = "pymedphys dicom anonymise -p".split() + [ temp_filepath ] try: subprocess.check_call(anon_file_private_command) assert not is_anonymised_file(temp_anon_filepath) assert is_anonymised_file(temp_anon_filepath, ignore_private_tags=True) assert exists(temp_filepath) finally: remove_file(temp_anon_filepath) # TODO: File anonymisation - unknown tag handling # # Calling a subprocess reloads BASELINE_DICOM_DICT... # Basic dir anonymisation assert not is_anonymised_directory(tmp_path) assert not exists(temp_anon_filepath) anon_dir_command = "pymedphys dicom anonymise".split() + [str(tmp_path)] try: subprocess.check_call(anon_dir_command) assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) finally: remove_file(temp_anon_filepath) finally: remove_file(temp_filepath)
def test_anonymise_directory(tmp_path): temp_filepath = tmp_path / "test.dcm" temp_anon_filepath = label_dicom_filepath_as_anonymised(temp_filepath) temp_record_filepath = tmp_path / "test_record.dcm" temp_anon_record_filepath = label_dicom_filepath_as_anonymised(temp_record_filepath) try: copyfile(get_rtplan_test_file_path(), temp_filepath) assert not is_anonymised_directory(tmp_path) # Test file deletion anon_path_list = anonymise_directory( tmp_path, delete_original_files=False, anonymise_filenames=False ) # # File should be anonymised but not dir, since original file # # is still present. assert is_anonymised_file(temp_anon_filepath) assert exists(temp_filepath) assert not is_anonymised_directory(tmp_path) assert anon_path_list is not None assert anon_path_list[0] == temp_anon_filepath remove_file(temp_anon_filepath) anon_path_list = anonymise_directory( tmp_path, delete_original_files=True, anonymise_filenames=False ) # # File and dir should be anonymised since original file should # # have been deleted. assert is_anonymised_file(temp_anon_filepath) assert not exists(temp_filepath) assert is_anonymised_directory(tmp_path) assert anon_path_list[0] == temp_anon_filepath # Test fail fast vs. fail at last # if the function fails fast, the specified removal # will not take place # if the function does not fail fail, the specified # removal will take place logging.warning("Testing fail fast") remove_file(temp_anon_filepath) copyfile(get_rtplan_test_file_path(), temp_filepath) copyfile(get_treatment_record_test_file_path(), temp_record_filepath) ds_record = pydicom.dcmread(temp_record_filepath, force=True) # deliberately add a DICOM element that is not in the current # dictionary ds_record.add_new([0x300A, 0x9999], "FL", [1.0, 1.0]) pydicom.dcmwrite(temp_record_filepath, ds_record) with pytest.raises((KeyError, ValueError)): anon_path_list = anonymise_directory( tmp_path, delete_original_files=True, anonymise_filenames=False, fail_fast=True, ) logging.warning(anon_path_list) assert exists(temp_filepath) with pytest.raises((KeyError, ValueError)): anon_path_list = anonymise_directory( tmp_path, delete_original_files=True, anonymise_filenames=False, fail_fast=False, ) logging.warning(anon_path_list) assert not exists(temp_filepath) finally: remove_file(temp_anon_filepath) remove_file(temp_anon_record_filepath)