Beispiel #1
0
def _remove_tag(dicom, item, field, value=None):
    """A wrapper to handle removal of a tag by calling tags.remove_tag.
       The user can optionally provide a value with a function
       to determine if a tag should be removed (returns True or False)
    """
    value = value or ""
    do_removal = True

    # The user can optionally provide a function to return a boolean
    if re.search("[:]", value):
        value_type, value_option = value.split(":", 1)
        if value_type.lower() == "func":

            # An item must be provided
            if item == None:
                bot.warning(
                    "The item parameter (dict) with values must be provided for a REMOVE func:%s"
                    % value_option)

            # The function must be included in the item
            if value_option not in item:
                bot.warning("%s not found as key included with item." %
                            value_option)

            # To the removal, this should return True/False
            # The calling function (currently) is required to handle parsing fields
            # that are tags.
            do_removal = item[value_option](dicom, value, field)
            if not isinstance(do_removal, bool):
                bot.warning(
                    "function %s returned an invalid type %s. Must be bool." %
                    (value_option, type(do_removal)))

        # A filter such as contains, notcontains, equals, etc.
        elif value_type.lower() in value_filters:

            # These functions are known to return boolean
            do_removal = apply_filter(
                dicom=dicom,
                field=field,
                filter_name=value_type,
                value=value_option or None,
            )

        else:
            bot.exit("%s is an invalid variable type for REMOVE." % value_type)

    if do_removal:
        dicom = remove_tag(dicom, field)
    return dicom
Beispiel #2
0
def _has_burned_pixels_single(dicom_file, force, deid):
    """has burned pixels single will evaluate one dicom file for burned in
    pixels based on 'filter' criteria in a deid. If deid is not provided,
    will use application default. The method proceeds as follows:

    1. deid is loaded, with criteria groups ordered from specific --> general
    2. image is run down the criteria, stops when hits and reports FLAG
    3. passing through the entire list gives status of pass

    The default deid has a greylist, whitelist, then blacklist

    Parameters
    =========
    dicom_file: the fullpath to the file to evaluate
    force: force reading of a potentially erroneous file
    deid: the full path to a deid specification. if not defined, only default used

    deid['filter']['dangerouscookie'] <-- filter list "dangerouscookie"

    --> This is what an item in the criteria looks like
         [{'coordinates': ['0,0,512,110'],
           'filters': [{'InnerOperators': [],
           'action': ['notequals'],
           'field': ['OperatorsName'],
           'operator': 'and',
           'value': ['bold bread']}],
         'name': 'criteria for dangerous cookie'}]


    Returns
    =======
    --> This is what a clean image looks like:
        {'flagged': False, 'results': []}

    --> This is what a flagged image looks like:
       {'flagged': True,
        'results': [
               {'reason': ' ImageType missing  or ImageType empty ',
                'group': 'blacklist',
                'coordinates': []}
            ]
        }
    """
    dicom = read_file(dicom_file, force=force)

    # Return list with lookup as dicom_file
    results = []
    global_flagged = False

    # Load criteria (actions) for flagging
    filters = deid.get_filters()
    if not filters:
        bot.warning("Deid provided does not have %filter.")
        return {"flagged": global_flagged, "results": results}

    for name, items in filters.items():
        for item in items:
            flags = []

            descriptions = []  # description for each group across items

            # If there aren't any filters but we have coordinates, assume True
            if not item.get("filters") and item.get("coordinates"):
                group_flags = [True]
                group_descriptions = [item.get("name", "")]

            else:
                group_flags = []  # evaluation for a single line
                group_descriptions = []
                for group in item["filters"]:

                    # You cannot pop from the list
                    for a in range(len(group["action"])):

                        action = group["action"][a]
                        field = group["field"][a]
                        value = ""

                        if len(group["value"]) > a:
                            value = group["value"][a]

                        flag = apply_filter(
                            dicom=dicom,
                            field=field,
                            filter_name=action,
                            value=value or None,
                        )
                        group_flags.append(flag)
                        description = "%s %s %s" % (field, action, value)

                        if len(group["InnerOperators"]) > a:
                            inner_operator = group["InnerOperators"][a]
                            group_flags.append(inner_operator)
                            description = "%s %s" % (description,
                                                     inner_operator)

                        group_descriptions.append(description)

            # At the end of a group, evaluate the inner group
            flag = evaluate_group(group_flags)

            # "Operator" is relevant for the outcome of the list of actions
            operator = ""
            if "operator" in group:
                if group["operator"] is not None:
                    operator = group["operator"]
                    flags.append(operator)

            flags.append(flag)
            reason = ("%s %s" %
                      (operator, " ".join(group_descriptions))).replace(
                          "\n", " ")
            descriptions.append(reason)

            # When we parse through a group, we evaluate based on all flags
            flagged = evaluate_group(flags=flags)

            if flagged is True:
                global_flagged = True
                reason = " ".join(descriptions)

                # Each coordinate is a list with [value, [coordinate]]
                # and if from: in the coordinate value, it indicates we get
                # the coordinate from some field (done here)
                for coordset in item["coordinates"]:
                    if "from:" in coordset[1]:
                        coordset[1] = extract_coordinates(dicom, coordset[1])

                result = {
                    "reason": reason,
                    "group": name,
                    "coordinates": item["coordinates"],
                }

                results.append(result)

    results = {"flagged": global_flagged, "results": results}
    return results
Beispiel #3
0
def _has_burned_pixels_single(dicom_file,force=True, deid=None):

    '''has burned pixels single will evaluate one dicom file for burned in
    pixels based on 'filter' criteria in a deid. If deid is not provided,
    will use application default. The method proceeds as follows:

    1. deid is loaded, with criteria groups ordered from specific --> general
    2. image is run down the criteria, stops when hits and reports FLAG
    3. passing through the entire list gives status of pass
    
    The default deid has a greylist, whitelist, then blacklist

    Parameters
    =========
    dicom_file: the fullpath to the file to evaluate
    force: force reading of a potentially erroneous file
    deid: the full path to a deid specification. if not defined, only default used

    deid['filter']['dangerouscookie'] <-- filter list "dangerouscookie"

    --> This is what an item in the criteria looks like
        [{'coordinates': ['0,0,512,110'],
          'filters': [{'InnerOperators': [],
          'action': ['notequals'],
          'field': ['OperatorsName'],
          'operator': 'and',
          'value': ['bold bread']}],
        'name': 'criteria for dangerous cookie'}]

    
    Returns
    =======
    --> This is what a clean image looks like:
        {'flagged': False, 'results': []}


    --> This is what a flagged image looks like:
       {'flagged': True,
        'results': [
                      {'reason': ' ImageType missing  or ImageType empty ',
                       'group': 'blacklist',
                       'coordinates': []}
                   ]
        }
    '''

    dicom = read_file(dicom_file,force=force)
    dicom_name = os.path.basename(dicom_file)
        
    # Load criteria (actions) for flagging
    if 'filter' not in deid:
        bot.error('Deid provided does not have %filter, exiting.')
        sys.exit(1)

    # Return list with lookup as dicom_file
    results = []
    global_flagged = False

    for name,items in deid['filter'].items():
        for item in items:
            flags = []

            descriptions = [] # description for each group across items

            for group in item['filters']:
                group_flags = []         # evaluation for a single line
                group_descriptions = []

                # You cannot pop from the list
                for a in range(len(group['action'])):
                    action = group['action'][a]
                    field = group['field'][a]
                    value = ''
                    if len(group['value']) > a:
                        value = group['value'][a]
                    flag = apply_filter(dicom=dicom,
                                        field=field,
                                        filter_name=action,
                                        value=value or None)
                    group_flags.append(flag)
                    description = "%s %s %s" %(field,action,value)
                    if len(group['InnerOperators']) > a:
                        inner_operator = group['InnerOperators'][a]
                        group_flags.append(inner_operator)
                        description = "%s %s" %(description,inner_operator)
                    group_descriptions.append(description)

                # At the end of a group, evaluate the inner group   
                flag = evaluate_group(group_flags)

                # "Operator" is relevant for the outcome of the list of actions 
                operator = ''
                if 'operator' in group:
                    if group['operator'] is not None:
                        operator = group['operator']
                        flags.append(operator)

                flags.append(flag)
                reason = ('%s %s' %(operator,' '.join(group_descriptions))).replace('\n',' ')
                descriptions.append(reason)

            group_name = ''
            if "name" in item:
                group_name = item['name']

            # When we parse through a group, we evaluate based on all flags
            flagged = evaluate_group(flags=flags)

            if flagged is True:
                global_flagged = True
                reason = ' '.join(descriptions)

                result = {'reason': reason,
                          'group': name,
                          'coordinates': item['coordinates'] }

                results.append(result)

    results = {'flagged': global_flagged,
               'results': results }
    return results