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_anonymise_dataset_and_all_is_anonymised_functions(tmp_path): # Create dataset with one instance of every identifying keyword and # run basic anonymisation tests ds = pydicom.dataset.Dataset() for keyword in IDENTIFYING_KEYWORDS: # Ignore file meta elements for now tag = hex(pydicom.datadict.tag_for_keyword(keyword)) if pydicom.tag.Tag(tag).group == 0x0002: continue value = _get_non_anonymous_replacement_value(keyword) setattr(ds, keyword, value) _check_is_anonymised_dataset_file_and_dir(ds, tmp_path, anon_is_expected=False) ds_anon = anonymise_dataset(ds) _check_is_anonymised_dataset_file_and_dir(ds_anon, tmp_path, anon_is_expected=True) # Test the anonymisation and check functions for each identifying # element individually. for elem in ds_anon.iterall(): # TODO: AffectedSOPInstanceUID and RequestedSOPInstanceUID # are not writing to file. Investigate when UID anonymisation is # implemented. if elem.keyword in ("AffectedSOPInstanceUID", "RequestedSOPInstanceUID"): continue ds_single_non_anon_value = deepcopy(ds_anon) setattr( ds_single_non_anon_value, elem.keyword, _get_non_anonymous_replacement_value(elem.keyword), ) _check_is_anonymised_dataset_file_and_dir( ds_single_non_anon_value, tmp_path, anon_is_expected=False ) ds_single_anon = anonymise_dataset(ds_single_non_anon_value) _check_is_anonymised_dataset_file_and_dir( ds_single_anon, tmp_path, anon_is_expected=True ) # Test correct handling of private tags ds_anon.add(pydicom.dataset.DataElement(0x0043102B, "SS", [4, 4, 0, 0])) _check_is_anonymised_dataset_file_and_dir( ds_anon, tmp_path, anon_is_expected=False, ignore_private_tags=False ) _check_is_anonymised_dataset_file_and_dir( ds_anon, tmp_path, anon_is_expected=True, ignore_private_tags=True ) ds_anon.remove_private_tags() _check_is_anonymised_dataset_file_and_dir( ds_anon, tmp_path, anon_is_expected=True, ignore_private_tags=False ) # Test blank anonymisation # # Sanity check _check_is_anonymised_dataset_file_and_dir(ds, tmp_path, anon_is_expected=False) ds_anon_blank = anonymise_dataset(ds, replace_values=False) _check_is_anonymised_dataset_file_and_dir( ds_anon_blank, tmp_path, anon_is_expected=True ) # Test handling of unknown tags by removing PatientName from # baseline dict patient_name_tag = pydicom.datadict.tag_for_keyword("PatientName") try: patient_name = get_baseline_dicom_dict().pop(patient_name_tag) with pytest.raises(ValueError) as e_info: anonymise_dataset(ds) assert str(e_info.value).count( "At least one of the non-private tags " "within your DICOM file is not within " "PyMedPhys's copy of the DICOM dictionary." ) ds_anon_delete_unknown = anonymise_dataset(ds, delete_unknown_tags=True) _check_is_anonymised_dataset_file_and_dir( ds_anon_delete_unknown, tmp_path, anon_is_expected=True ) with pytest.raises(AttributeError) as e_info: ds_anon_delete_unknown.PatientName # pylint: disable = pointless-statement assert str(e_info.value).count( "'Dataset' object has no attribute " "'PatientName'" ) ds_anon_ignore_unknown = anonymise_dataset(ds, delete_unknown_tags=False) _check_is_anonymised_dataset_file_and_dir( ds_anon_ignore_unknown, tmp_path, anon_is_expected=True ) assert patient_name_tag in ds_anon_ignore_unknown finally: get_baseline_dicom_dict().setdefault(patient_name_tag, patient_name) # Test copy_dataset=False: anonymise_dataset(ds, copy_dataset=False) assert is_anonymised_dataset(ds)
def test_anonymised_dataset_with_nested_name(): nested_name = dicom_dataset_from_dict( {"OverrideSequence": [{"OperatorsName": "George"}]} ) assert not is_anonymised_dataset(nested_name)
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_anonymised_dataset_with_empty_patient_sex(): blank_sex_ds = dicom_dataset_from_dict({"PatientSex": None}) assert is_anonymised_dataset(blank_sex_ds) hardcode_replace_ds = anonymise_dataset(blank_sex_ds) assert hardcode_replace_ds["PatientSex"].value is None