def test_adjust_machine_name(): new_name = 'new_name' original_ds = dicom_dataset_from_dict({ 'BeamSequence': [ { 'TreatmentMachineName': 'hello' }, { 'TreatmentMachineName': 'george' } ] }) expected_ds = dicom_dataset_from_dict({ 'BeamSequence': [ { 'TreatmentMachineName': new_name }, { 'TreatmentMachineName': new_name } ] }) adjusted_ds = adjust_machine_name(original_ds, new_name) assert adjusted_ds != original_ds assert adjusted_ds == expected_ds command = ( 'pymedphys dicom adjust-machine-name'.split() + [ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME, new_name]) compare_dicom_cli(command, original_ds, expected_ds)
def test_structure_name_based_RED_append(): electron_density_to_use = 0.5 original_ds = dicom_dataset_from_dict({ "StructureSetROISequence": [ { "ROINumber": 1, "ROIName": "a_structure RED={}".format(electron_density_to_use), }, { "ROINumber": 2, "ROIName": "dont_change_me" }, ], "RTROIObservationsSequence": [ { "ReferencedROINumber": 1 }, { "ReferencedROINumber": 2 }, ], }) expected_ds = dicom_dataset_from_dict( { "RTROIObservationsSequence": [ { "ReferencedROINumber": 1, "ROIPhysicalPropertiesSequence": [{ "ROIPhysicalProperty": "REL_ELEC_DENSITY", "ROIPhysicalPropertyValue": electron_density_to_use, }], }, { "ReferencedROINumber": 2 }, ] }, template_ds=original_ds, ) adjusted_ds = adjust_RED_by_structure_name(original_ds) assert adjusted_ds != original_ds assert str(expected_ds) == str(adjusted_ds) command = "pymedphys dicom adjust-RED-by-structure-name".split() + [ ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME, ] compare_dicom_cli(command, original_ds, expected_ds)
def test_structure_name_based_RED_append(): electron_density_to_use = 0.5 original_ds = dicom_dataset_from_dict({ 'StructureSetROISequence': [ { 'ROINumber': 1, 'ROIName': 'a_structure RED={}'.format(electron_density_to_use) }, { 'ROINumber': 2, 'ROIName': 'dont_change_me' } ], 'RTROIObservationsSequence': [ { 'ReferencedROINumber': 1, }, { 'ReferencedROINumber': 2, } ] }) expected_ds = dicom_dataset_from_dict({ 'RTROIObservationsSequence': [ { 'ReferencedROINumber': 1, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'REL_ELEC_DENSITY', 'ROIPhysicalPropertyValue': electron_density_to_use } ] }, { 'ReferencedROINumber': 2 }, ] }, template_ds=original_ds) adjusted_ds = adjust_RED_by_structure_name(original_ds) assert adjusted_ds != original_ds assert str(expected_ds) == str(adjusted_ds) command = ( 'pymedphys dicom adjust-RED-by-structure-name'.split() + [ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME]) compare_dicom_cli(command, original_ds, expected_ds)
def test_copy(): dont_change_string = "don't change me" to_be_changed_string = 'do change me' new_manufactuer = 'george' dataset_to_be_copied = dicom_dataset_from_dict( {'Manufacturer': dont_change_string}) dataset_to_be_viewed = dicom_dataset_from_dict( {'Manufacturer': to_be_changed_string}) dicom_base_copy = DicomBase(dataset_to_be_copied) dicom_base_view = DicomBase(dataset_to_be_viewed, copy=False) dicom_base_copy.dataset.Manufacturer = new_manufactuer dicom_base_view.dataset.Manufacturer = new_manufactuer assert dataset_to_be_copied.Manufacturer == dont_change_string assert dataset_to_be_viewed.Manufacturer == new_manufactuer
def test_anonymise(): expected_dataset = dicom_dataset_from_dict({ 'Manufacturer': 'PyMedPhys', 'PatientName': 'Anonymous' }) dicom = DicomBase.from_dict({ 'Manufacturer': 'PyMedPhys', 'PatientName': 'Python^Monte' }) dicom.anonymise(inplace=True) assert dicom.dataset == expected_dataset
def test_anonymise(): expected_dataset = dicom_dataset_from_dict({ "Manufacturer": "PyMedPhys", "PatientName": "Anonymous" }) dicom = DicomBase.from_dict({ "Manufacturer": "PyMedPhys", "PatientName": "Python^Monte" }) dicom.anonymise(inplace=True) assert dicom.dataset == expected_dataset
def test_adjust_machine_name(): new_name = "new_name" original_ds = dicom_dataset_from_dict({ "BeamSequence": [ { "TreatmentMachineName": "hello" }, { "TreatmentMachineName": "george" }, ] }) expected_ds = dicom_dataset_from_dict({ "BeamSequence": [ { "TreatmentMachineName": new_name }, { "TreatmentMachineName": new_name }, ] }) adjusted_ds = adjust_machine_name(original_ds, new_name) assert adjusted_ds != original_ds assert adjusted_ds == expected_ds command = "pymedphys dicom adjust-machine-name".split() + [ ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME, new_name, ] compare_dicom_cli(command, original_ds, expected_ds)
def test_dicom_from_dict(): baseline_dataset = pydicom.Dataset() baseline_dataset.Manufacturer = "PyMedPhys" beam_sequence = pydicom.Dataset() beam_sequence.Manufacturer = "PyMedPhys" baseline_dataset.BeamSequence = [beam_sequence] created_dataset = dicom_dataset_from_dict({ "Manufacturer": "PyMedPhys", "BeamSequence": [{ "Manufacturer": "PyMedPhys" }] }) assert created_dataset == baseline_dataset
def test_dicom_from_dict(): baseline_dataset = pydicom.Dataset() baseline_dataset.Manufacturer = 'PyMedPhys' beam_sequence = pydicom.Dataset() beam_sequence.Manufacturer = 'PyMedPhys' baseline_dataset.BeamSequence = [beam_sequence] created_dataset = dicom_dataset_from_dict({ 'Manufacturer': 'PyMedPhys', 'BeamSequence': [{ 'Manufacturer': 'PyMedPhys' }] }) assert created_dataset == baseline_dataset
def test_pull_structure(): dicom_structure = dicom_dataset_from_dict({ 'StructureSetROISequence': [{ 'ROIName': A_STRUCTURE.name, 'ROINumber': A_STRUCTURE.number }, { 'ROIName': ANOTHER_STRUCTURE.name, 'ROINumber': ANOTHER_STRUCTURE.number }], 'ROIContourSequence': [ # Sequence purposely placed in reverse order to ensure ROI # number is being used and not list order. create_contour_sequence_dict(ANOTHER_STRUCTURE), create_contour_sequence_dict(A_STRUCTURE) ] }) x, y, z = pull_structure(A_STRUCTURE.name, dicom_structure) assert np.all(x == np.array(A_STRUCTURE.coords)[:, 0, :]) assert np.all(y == np.array(A_STRUCTURE.coords)[:, 1, :]) assert np.all(z == np.array(A_STRUCTURE.coords)[:, 2, :])
def test_electron_density_append(): adjustment_map = { "to_be_changed 1": 1.0, "to_be_changed 2": 0.5, "to_be_changed 3": 1.5, } excess_adjustment_map = { **adjustment_map, **{ "this_structure_doesnt_exist": 1.0 } } original_ds = dicom_dataset_from_dict({ "StructureSetROISequence": [ { "ROINumber": 1, "ROIName": "to_be_changed 1" }, { "ROINumber": 2, "ROIName": "dont_change_me" }, { "ROINumber": 10, "ROIName": "to_be_changed 2" }, { "ROINumber": 99, "ROIName": "to_be_changed 3" }, ], "RTROIObservationsSequence": [ { "ReferencedROINumber": 1, "ROIPhysicalPropertiesSequence": [{ "ROIPhysicalProperty": "EFFECTIVE_Z", "ROIPhysicalPropertyValue": 6, }], }, { "ReferencedROINumber": 2 }, { "ReferencedROINumber": 10 }, { "ReferencedROINumber": 99, "ROIPhysicalPropertiesSequence": [{ "ROIPhysicalProperty": "REL_ELEC_DENSITY", "ROIPhysicalPropertyValue": 0, }], }, ], }) expected_ds = dicom_dataset_from_dict( { "RTROIObservationsSequence": [ { "ReferencedROINumber": 1, "ROIPhysicalPropertiesSequence": [ { "ROIPhysicalProperty": "EFFECTIVE_Z", "ROIPhysicalPropertyValue": 6, }, { "ROIPhysicalProperty": "REL_ELEC_DENSITY", "ROIPhysicalPropertyValue": adjustment_map["to_be_changed 1"], }, ], }, { "ReferencedROINumber": 2 }, { "ReferencedROINumber": 10, "ROIPhysicalPropertiesSequence": [{ "ROIPhysicalProperty": "REL_ELEC_DENSITY", "ROIPhysicalPropertyValue": adjustment_map["to_be_changed 2"], }], }, { "ReferencedROINumber": 99, "ROIPhysicalPropertiesSequence": [{ "ROIPhysicalProperty": "REL_ELEC_DENSITY", "ROIPhysicalPropertyValue": adjustment_map["to_be_changed 3"], }], }, ] }, template_ds=original_ds, ) adjusted_ds = adjust_rel_elec_density(original_ds, adjustment_map) assert adjusted_ds != original_ds assert str(expected_ds) == str(adjusted_ds) adjusted_with_excess_ds = adjust_rel_elec_density( original_ds, excess_adjustment_map, ignore_missing_structure=True) assert adjusted_with_excess_ds != original_ds assert str(expected_ds) == str(adjusted_with_excess_ds) excess_adjustment_map_as_list = [[ "{}".format(key), item ] for key, item in excess_adjustment_map.items()] excess_adjustment_map_flat = np.concatenate( excess_adjustment_map_as_list).tolist() command = ("pymedphys dicom adjust-RED -i ".split() + [ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME] + excess_adjustment_map_flat) compare_dicom_cli(command, original_ds, expected_ds)
def test_anonymise_dataset_and_all_is_anonymised_functions(): # Create dict with one instance of every identifying keyword and # run basic anonymisation tests non_anon_dict = dict.fromkeys(IDENTIFYING_KEYWORDS) for key in non_anon_dict: non_anon_dict[key] = _get_non_anonymous_replacement_value(key) ds = dicom_dataset_from_dict(non_anon_dict) _check_is_anonymised_dataset_file_and_dir(ds, anon_is_expected=False) ds_anon = anonymise_dataset(ds) _check_is_anonymised_dataset_file_and_dir(ds_anon, anon_is_expected=True) # Test anonymisation (and check thereof) for each identifying # element individually. for elem in ds_anon.iterall(): 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, anon_is_expected=False) ds_single_anon = anonymise_dataset(ds_single_non_anon_value) _check_is_anonymised_dataset_file_and_dir(ds_single_anon, anon_is_expected=True) # Test correct handling of private tags ds_anon.add(DataElement(0x0043102b, 'SS', [4, 4, 0, 0])) _check_is_anonymised_dataset_file_and_dir(ds_anon, anon_is_expected=False, ignore_private_tags=False) _check_is_anonymised_dataset_file_and_dir(ds_anon, anon_is_expected=True, ignore_private_tags=True) ds_anon.remove_private_tags() _check_is_anonymised_dataset_file_and_dir(ds_anon, anon_is_expected=True, ignore_private_tags=False) # Test blank anonymisation # # Sanity check _check_is_anonymised_dataset_file_and_dir(ds, anon_is_expected=False) ds_anon_blank = anonymise_dataset(ds, replace_values=False) _check_is_anonymised_dataset_file_and_dir(ds_anon_blank, anon_is_expected=True) # Test handling of unknown tags by removing PatientName from # baseline dict patient_name_tag = tag_for_keyword('PatientName') try: patient_name = BaselineDicomDictionary.pop(patient_name_tag) with pytest.raises(ValueError) as e_info: anonymise_dataset(ds) assert str(e_info).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, anon_is_expected=True) with pytest.raises(AttributeError) as e_info: ds_anon_delete_unknown.PatientName assert str(e_info).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, anon_is_expected=True) assert patient_name_tag in ds_anon_ignore_unknown finally: BaselineDicomDictionary.setdefault(patient_name_tag, patient_name) # Test copy_dataset=False: anonymise_dataset(ds, copy_dataset=False) assert is_anonymised_dataset(ds)
def test_electron_density_append(): adjustment_map = { 'to_be_changed 1': 1.0, 'to_be_changed 2': 0.5, 'to_be_changed 3': 1.5 } excess_adjustment_map = { **adjustment_map, **{ 'this_structure_doesnt_exist': 1.0 } } original_ds = dicom_dataset_from_dict({ 'StructureSetROISequence': [ { 'ROINumber': 1, 'ROIName': 'to_be_changed 1' }, { 'ROINumber': 2, 'ROIName': 'dont_change_me' }, { 'ROINumber': 10, 'ROIName': 'to_be_changed 2' }, { 'ROINumber': 99, 'ROIName': 'to_be_changed 3' }, ], 'RTROIObservationsSequence': [ { 'ReferencedROINumber': 1, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'EFFECTIVE_Z', 'ROIPhysicalPropertyValue': 6 } ] }, { 'ReferencedROINumber': 2, }, { 'ReferencedROINumber': 10, }, { 'ReferencedROINumber': 99, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'REL_ELEC_DENSITY', 'ROIPhysicalPropertyValue': 0 } ] } ] }) expected_ds = dicom_dataset_from_dict({ 'RTROIObservationsSequence': [ { 'ReferencedROINumber': 1, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'EFFECTIVE_Z', 'ROIPhysicalPropertyValue': 6 }, { 'ROIPhysicalProperty': 'REL_ELEC_DENSITY', 'ROIPhysicalPropertyValue': adjustment_map['to_be_changed 1'] } ] }, { 'ReferencedROINumber': 2 }, { 'ReferencedROINumber': 10, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'REL_ELEC_DENSITY', 'ROIPhysicalPropertyValue': adjustment_map['to_be_changed 2'] } ] }, { 'ReferencedROINumber': 99, 'ROIPhysicalPropertiesSequence': [ { 'ROIPhysicalProperty': 'REL_ELEC_DENSITY', 'ROIPhysicalPropertyValue': adjustment_map['to_be_changed 3'] } ] } ] }, template_ds=original_ds) adjusted_ds = adjust_rel_elec_density( original_ds, adjustment_map) assert adjusted_ds != original_ds assert str(expected_ds) == str(adjusted_ds) adjusted_with_excess_ds = adjust_rel_elec_density( original_ds, excess_adjustment_map, ignore_missing_structure=True) assert adjusted_with_excess_ds != original_ds assert str(expected_ds) == str(adjusted_with_excess_ds) excess_adjustment_map_as_list = [ ['{}'.format(key), item] for key, item in excess_adjustment_map.items() ] excess_adjustment_map_flat = np.concatenate( excess_adjustment_map_as_list).tolist() command = ( 'pymedphys dicom adjust-RED -i '.split() + [ORIGINAL_DICOM_FILENAME, ADJUSTED_DICOM_FILENAME] + excess_adjustment_map_flat) compare_dicom_cli(command, original_ds, expected_ds)