예제 #1
0
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)
예제 #2
0
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)
예제 #3
0
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)
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
예제 #7
0
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)
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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, :])
예제 #11
0
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)
예제 #12
0
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)
예제 #13
0
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)