def test_field_expansion(self):
        print("Test deid.dicom.fields expand_field_expression")
        from deid.dicom.fields import expand_field_expression

        dicom = get_dicom(self.dataset)
        contenders = dicom.dir()

        print("Testing that field expansion works for basic tags")
        expand_field_expression(dicom=dicom,
                                field="endswith:Time",
                                contenders=contenders)

        print("Testing that field expansion works including private tags")
        contenders += [e.tag for e in get_private(dicom)]
        expand_field_expression(dicom=dicom,
                                field="endswith:Time",
                                contenders=contenders)

        print("Testing that we can also search private tags based on numbers.")
        fields = expand_field_expression(dicom=dicom,
                                         field="contains:0019",
                                         contenders=contenders)

        # We should have a tag object in the list now!
        assert isinstance(fields[0], BaseTag)

        print("Testing nested private tags")
        dataset = get_dataset("animals")  # includes nested private tags
        dicom = get_dicom(dataset)
Exemple #2
0
    def perform_action(self, field, value, action):
        """perform action takes an action (dictionary with field, action, value)
        and performs the action on the loaded dicom.

        Parameters
        ==========
        fields: if provided, a filtered list of fields for expand
        action: the action from the parsed deid to take
           "field" (eg, PatientID) the header field to process
           "action" (eg, REPLACE) what to do with the field
           "value": if needed, the field from the response to replace with

        """
        # Validate the action
        if action not in valid_actions:
            bot.warning("%s in not a valid choice. Defaulting to blanked." %
                        action)
            action = "BLANK"

        # A values list returns fields with the value (can be private tags if not removed)
        if re.search("^values", field):
            values = self.lookup.get(re.sub("^values:", "", field), [])
            fields = self.find_by_values(values=values)

        # A fields list is used vertabim
        # In expand_field_expression below, the stripped_tag is being passed in to field.  At this point,
        # expanders for %fields lists have already been processed and each of the contenders is an
        # identified, unique field.  It is important to use stripped_tag at this point instead of
        # element.keyword as private tags will not have a keyword and can only be identified by tag number.
        elif re.search("^fields", field):
            listing = {}
            for uid, contender in self.lookup.get(
                    re.sub("^fields:", "", field), {}).items():
                listing.update(
                    expand_field_expression(
                        field=contender.stripped_tag,
                        dicom=self.dicom,
                        contenders=self.fields,
                    ))
            fields = listing

        else:
            # If there is an expander applied to field, we iterate over
            fields = expand_field_expression(field=field,
                                             dicom=self.dicom,
                                             contenders=self.fields)

        # If it's an addition, we might not have fields
        if action == "ADD":
            self.add_field(field, value)

        # Otherwise, these are operations on existing fields
        else:
            """clone the fields dictionary. delete actions must also delete from the fields dictionary.
            performing the clone and iterating on the clone allows the deletions while preventing a
            runtime error - "dictionary changed size during iterations"
            """
            temp_fields = deepcopy(fields)
            for uid, field in temp_fields.items():
                self._run_action(field=field, action=action, value=value)
Exemple #3
0
    def test_field_expansion(self):
        print("Test deid.dicom.fields expand_field_expression")
        from deid.dicom.fields import expand_field_expression

        dicom = get_dicom(self.dataset)

        contenders = get_fields(dicom)

        print("Testing that field expansion works for basic tags")
        fields = expand_field_expression(dicom=dicom,
                                         field="endswith:Time",
                                         contenders=contenders)

        # The fields returned should end in time
        for uid, field in fields.items():
            assert field.name.endswith("Time")

        print("Testing that we can also search private tags based on numbers.")
        fields = expand_field_expression(dicom=dicom,
                                         field="contains:0019",
                                         contenders=contenders)

        # The fields returned should include tag group or element 0019
        for uid, field in fields.items():
            assert "0019" in uid

        print("Testing nested private tags")
        dataset = get_dataset("animals")  # includes nested private tags
        dicom = get_dicom(dataset)
Exemple #4
0
    def test_expand_field_expression(self):
        from deid.dicom.fields import expand_field_expression
        dicom = get_dicom(self.dataset)
        dicom.AcquisitionDateTime = '20131210081530'
        dicom.data_element("AcquisitionDateTime").VR = 'DT'

        print("Case 1: Test startswith")
        fields = expand_field_expression("startswith:Patient", dicom)
        expected = ['PatientBirthDate', 'PatientID', 'PatientName',
                    'PatientOrientation', 'PatientSex']
        self.assertEqual(fields, expected)

        print("Case 2: Test endswith")
        fields = expand_field_expression("endswith:Date", dicom)
        expected = ['PatientBirthDate', 'StudyDate']
        self.assertEqual(fields, expected)

        print("Case 3: Test contains")
        fields = expand_field_expression("contains:Date", dicom)
        expected = ['AcquisitionDateTime', 'PatientBirthDate', 'StudyDate']
        self.assertEqual(fields, expected)

        print("Case 4: Test except")
        fields = expand_field_expression("except:Patient", dicom)
        expected = ['AccessionNumber', 'AcquisitionDateTime',
                    'BitsAllocated', 'BitsStored', 'Columns',
                    'ConversionType', 'HighBit', 'ImageComments',
                    'InstanceNumber', 'InstitutionName',
                    'LossyImageCompression', 'LossyImageCompressionMethod',
                    'NameOfPhysiciansReadingStudy', 'OperatorsName',
                    'PhotometricInterpretation', 'PixelData',
                    'PixelRepresentation', 'PlanarConfiguration',
                    'ReferringPhysicianName', 'Rows', 'SOPClassUID',
                    'SOPInstanceUID', 'SamplesPerPixel', 'SeriesInstanceUID',
                   'SeriesNumber', 'SpecificCharacterSet', 'StudyDate',
                    'StudyID', 'StudyInstanceUID', 'StudyTime']
        self.assertEqual(fields, expected)

        print("Case 5: Test all")
        fields = expand_field_expression("all", dicom)
        expected = ['AccessionNumber', 'AcquisitionDateTime', 'BitsAllocated',
                    'BitsStored', 'Columns', 'ConversionType', 'HighBit',
                    'ImageComments', 'InstanceNumber', 'InstitutionName',
                    'LossyImageCompression', 'LossyImageCompressionMethod',
                    'NameOfPhysiciansReadingStudy', 'OperatorsName',
                    'PatientBirthDate', 'PatientID', 'PatientName',
                    'PatientOrientation', 'PatientSex',
                    'PhotometricInterpretation', 'PixelData',
                    'PixelRepresentation', 'PlanarConfiguration',
                    'ReferringPhysicianName', 'Rows', 'SOPClassUID',
                    'SOPInstanceUID', 'SamplesPerPixel', 'SeriesInstanceUID',
                    'SeriesNumber', 'SpecificCharacterSet', 'StudyDate',
                    'StudyID', 'StudyInstanceUID', 'StudyTime']
        self.assertEqual(fields, expected)
Exemple #5
0
    def perform_action(self, field, value, action):
        """perform action takes an action (dictionary with field, action, value)
           and performs the action on the loaded dicom.

           Parameters
           ==========
           fields: if provided, a filtered list of fields for expand
           action: the action from the parsed deid to take
              "field" (eg, PatientID) the header field to process
              "action" (eg, REPLACE) what to do with the field
              "value": if needed, the field from the response to replace with

        """
        # Validate the action
        if action not in valid_actions:
            bot.warning("%s in not a valid choice. Defaulting to blanked." %
                        action)
            action = "BLANK"

        # A values list returns fields with the value (can be private tags if not removed)
        if re.search("^values", field):
            values = self.lookup.get(re.sub("^values:", "", field), [])
            fields = self.find_by_values(values=values)

        # A fields list is used vertabim
        elif re.search("^fields", field):
            listing = {}
            for uid, contender in self.lookup.get(
                    re.sub("^fields:", "", field), {}).items():
                listing.update(
                    expand_field_expression(
                        field=contender.element.keyword,
                        dicom=self.dicom,
                        contenders=self.fields,
                    ))
            fields = listing

        else:
            # If there is an expander applied to field, we iterate over
            fields = expand_field_expression(field=field,
                                             dicom=self.dicom,
                                             contenders=self.fields)

        # If it's an addition, we might not have fields
        if action == "ADD":
            self.add_field(field, value)

        # Otherwise, these are operations on existing fields
        else:
            for uid, field in fields.items():
                self._run_action(field=field, action=action, value=value)
Exemple #6
0
def perform_action(dicom, action, item=None, fields=None, return_seen=False):
    """perform action takes  

       Parameters
       ==========
       dicom: a loaded dicom file (pydicom read_file)
       item: a dictionary with keys as fields, values as values
       fields: if provided, a filtered list of fields for expand
       action: the action from the parsed deid to take
          "deid" (eg, PatientID) the header field to process
          "action" (eg, REPLACE) what to do with the field
          "value": if needed, the field from the response to replace with
    """
    field = action.get(
        "field")  # e.g: PatientID, endswith:ID, values:name, fields:name
    value = action.get("value")  # "suid" or "var:field"
    action = action.get("action")  # "REPLACE"

    # Validate the action
    if action not in valid_actions:
        bot.warning("%s in not a valid choice. Defaulting to blanked." %
                    action)
        action = "BLANK"

    # If values or fields is provided, ids is required
    if re.search("^(values|fields)", field):
        if not item:
            bot.exit(
                "An item lookup must be provided to reference a list of values or fields."
            )

        # A values list returns fields with the value (can be private tags if not removed)
        if re.search("^values", field):
            values = item.get(re.sub("^values:", "", field), [])
            fields = find_by_values(values=values, dicom=dicom)

        # A fields list is used vertabim
        elif re.search("^fields", field):
            listing = []
            for contender in item.get(re.sub("^fields:", "", field), []):
                listing += expand_field_expression(field=contender,
                                                   dicom=dicom,
                                                   contenders=fields)
            fields = listing

    else:
        # If there is an expander applied to field, we iterate over
        fields = expand_field_expression(field=field,
                                         dicom=dicom,
                                         contenders=fields)

    # Keep track of fields we have seen
    seen = []

    # An expanded field must END with that field
    expanded_regexp = "__%s$" % field

    for field in fields:

        # This key can be for a string or tag
        seen.append(field)

        # Handle top level field, this can be a key (string) or tag
        _perform_action(dicom=dicom,
                        field=field,
                        item=item,
                        action=action,
                        value=value)

    # Expand sequences
    if item:
        expanded_fields = [
            x for x in item if re.search(expanded_regexp, str(x))
        ]

        # FieldA__FieldB
        for expanded_field in expanded_fields:
            _perform_expanded_action(
                dicom=dicom,
                expanded_field=expanded_field,
                item=item,
                action=action,
                value=value,
            )

    if return_seen:
        return dicom, seen
    return dicom