예제 #1
0
def test_reject_kogsps_fail(dataset):
    """Datasets that should be rejected"""

    with pytest.raises(DeidentificationException):
        Core(profile=Profile(rule_sets=[]), bouncers=[RejectKOGSPS()]).deidentify(
            dataset
        )
예제 #2
0
def create_default_core(
    safe_private_definition: SafePrivateDefinition = None,
    location_list: PIILocationList = None,
) -> Core:
    """A default deidentification core with the following profile:

    * basic_profile
    * clean_descriptors
    * retain_patient_characteristics
    * retain_device_id
    * retain_safe_private


    Parameters
    ----------
    safe_private_definition: SafePrivateDefinition, optional
        Which private tags are safe to keep. Defaults to keeping none
    location_list: PIILocationList, optional
        Definition of where to remove burnt in information from images.
        Defaults to simply rejecting all datasets that might have burnt in
        information

    """
    sets = get_dicom_rule_sets(safe_private_definition)
    profile = Profile(  # Choose which rule sets to use
        name="idiscore default profile",
        rule_sets=[
            sets.basic_profile,
            sets.clean_descriptors,
            sets.retain_patient_characteristics,
            sets.retain_device_id,
            sets.retain_safe_private,
        ],
    )
    return create_core(profile=profile, location_list=location_list,)
예제 #3
0
def test_reject_non_standard():

    a_core = Core(profile=Profile(rule_sets=[]), bouncers=[RejectNonStandardDicom()])

    # this should not raise anything
    a_core.deidentify(quick_dataset(SOPClassUID="1.2.840.10008"))

    with pytest.raises(DeidentificationException):
        a_core.deidentify(quick_dataset(SOPClassUID="123"))
예제 #4
0
def test_core_description():
    """Human readable answer to the question 'what does this deidentifier do?'"""

    sets = DICOMRuleSets()
    profile = Profile(rule_sets=[
        sets.basic_profile,
        sets.clean_descriptors,
        sets.clean_graphics,
        sets.retain_modified_dates,
        sets.retain_safe_private,
    ])

    final_set = profile.flatten()
    assert len(final_set.rules) == 442

    core = Core(profile=profile, bouncers=[RejectKOGSPS])
    test = core.description()
    print(test)
예제 #5
0
def test_realistic_profile():
    """Run a file through a profile that has several options"""

    sets = DICOMRuleSets()
    profile = Profile(rule_sets=[
        sets.basic_profile,
        sets.clean_descriptors,
        sets.clean_graphics,
        sets.retain_modified_dates,
        sets.retain_safe_private,
    ])

    final_set = profile.flatten()
    assert len(final_set.rules) == 442

    core = Core(profile=profile)
    dataset = CTDatasetFactory()
    original = deepcopy(dataset)
    deidentified = core.deidentify(dataset)

    assert original.PatientID != deidentified.PatientID
예제 #6
0
def test_profile_flatten(some_pid_rules):
    """A profile can have multiple rule sets, but with flatten you should end up
    with one rule per DICOM tag
    """
    hash_name = Rule(SingleTag("PatientName"), Hash())

    # initial set
    set1 = RuleSet(rules=[some_pid_rules[0], hash_name])
    # set with a different rule for PatientID
    set2 = RuleSet(
        rules=[some_pid_rules[1],
               Rule(SingleTag("Modality"), Remove())])

    profile = Profile(rule_sets=[set1, set2])

    # The PatientID rule of set2 should be chosen when flattening
    assert some_pid_rules[1] in profile.flatten().rules
    assert some_pid_rules[0] not in profile.flatten().rules

    # if another set is added, the rules from this should overrule earlier
    set3 = RuleSet(name="another set", rules=[some_pid_rules[2]])
    assert some_pid_rules[2] in profile.flatten(
        additional_rule_sets=[set3]).rules
    # but any original rule that was not overwritten should still be present
    assert hash_name in profile.flatten(additional_rule_sets=[set3]).rules
예제 #7
0
def test_core_deidentify_safe_private(a_dataset, a_safe_private_definition):
    """Private elements marked as safe should not be removed by Clean()"""

    assert Tag("00b10010") in a_dataset  # a private creator tag
    assert Tag("00b11001") in a_dataset  # and a private tag

    # A core instance that should clean() private tags, but one tag is deemed safe
    ruleset = RuleSet(
        [Rule(PrivateTags(), Clean(safe_private=a_safe_private_definition))])
    core = Core(profile=Profile([ruleset]))

    # One tag should be kept
    deltas = extract_signature(deidentifier=core, dataset=a_dataset)
    assert {x.tag: x for x in deltas}[Tag("00b10010")].status == "REMOVED"
    assert {x.tag: x for x in deltas}[Tag("00b11001")].status == "UNCHANGED"

    # but only so long as dataset has modality = CT
    a_dataset.Modality = "US"
    deltas = extract_signature(deidentifier=core, dataset=a_dataset)
    assert {x.tag: x for x in deltas}[Tag("00b10010")].status == "REMOVED"
    assert {x.tag: x for x in deltas}[Tag("00b11001")].status == "REMOVED"
예제 #8
0
"""You can set your own rules for specific DICOM tags. Be aware that this might

mean the deidentification is no longer DICOM-complient
"""

import pydicom
from idiscore.core import Core, Profile
from idiscore.defaults import get_dicom_rule_sets
from idiscore.identifiers import RepeatingGroup, SingleTag
from idiscore.operators import Hash, Remove
from idiscore.rules import Rule, RuleSet

# Custom rules that will hash the patient name and remove all curve data
my_ruleset = RuleSet(
    rules=[
        Rule(SingleTag("PatientName"), Hash()),
        Rule(RepeatingGroup("50xx,xxxx"), Remove()),
    ],
    name="My Custom RuleSet",
)

sets = get_dicom_rule_sets()  # Contains official DICOM deidentification rules
profile = Profile(  # add custom rules to basic profile
    rule_sets=[sets.basic_profile, my_ruleset])
core = Core(profile)  # Create an deidentification core

# read a DICOM dataset from file and write to another
core.deidentify(pydicom.read("my_file.dcm")).save_as("deidentified.dcm")
예제 #9
0
def test_reject_kogsps_pass(dataset):
    """Datasets that should be passed"""
    # should not raise exceptions
    assert Core(profile=Profile(rule_sets=[]), bouncers=[RejectKOGSPS()]).deidentify(
        dataset
    )
예제 #10
0
def a_core_with_some_rules(some_rules) -> Core:
    """Core instance with a three-rule profile"""
    return Core(profile=Profile([RuleSet(some_rules)]))
예제 #11
0
"""Basic example of deidentifying a single file"""

import pydicom
from idiscore.core import Core, Profile
from idiscore.defaults import get_dicom_rule_sets

sets = get_dicom_rule_sets()  # Contains official DICOM deidentification rules
profile = Profile(  # Choose which rule sets to use
    rule_sets=[
        sets.basic_profile, sets.retain_modified_dates, sets.retain_device_id
    ])
core = Core(profile)  # Create an deidentification core

# read a DICOM dataset from file and write to another
core.deidentify(pydicom.read("my_file.dcm")).save_as("deidentified.dcm")