Source code for deid.utils.actions

__author__ = "Vanessa Sochat"
__copyright__ = "Copyright 2016-2022, Vanessa Sochat"
__license__ = "MIT"

import re
from datetime import datetime, timedelta

import dateutil.parser

from deid.logger import bot


[docs]def parse_value(dicom, value, item=None, field=None, funcs=None): """ Parse_value will parse the value field of an action. This function returns either: 1. the string (string or from function) 2. a variable looked up (var:FieldName) """ # custom function lookup funcs = funcs or {} # If item is passed as None if item is None: item = dict() # Does the user want a custom value? if re.search("[:]", value): value_type, value_option = value.split(":", 1) if value_type.lower() == "var": # If selected variable not provided, skip if value_option not in item: return None return item[value_option] # The user wants to use a deid provided function elif value_type.lower() == "deid_func": # There can be additional key=value pairs try: value_option, extras = value_option.split(" ", 1) except Exception: extras = "" pass if value_option not in funcs: bot.warning("%s not a known deid provided function." % (value_option)) return None print(extras) # item is the lookup, value from the recipe, and field # The field is an entire dicom element object return funcs[value_option]( dicom=dicom, value=value, field=field, item=item, extras=extras ) # The user is providing a specific function elif value_type.lower() == "func": if value_option not in item: bot.warning("%s not found in item lookup." % (value_option)) return None # item is the lookup, value from the recipe, and field # The field is an entire dicom element object return item[value_option](dicom=dicom, value=value, field=field, item=item) bot.warning("%s is not a valid value type, skipping." % (value_type)) return None return value
[docs]def parse_keyvalue_pairs(pairs): """ Given a listing of extra arguments, parse into lookup dict. """ values = {} if not pairs: return values for pair in pairs.split(" "): if "=" not in pair: continue key, value = pair.split("=", 1) value = value.strip() # Ensure we convert booleans and none/null if value == "true": value = True if value == "false": value = False if value in ["none", "null"]: value = None values[key.strip()] = value return values
[docs]def get_func(function_name): """ Get_func will return a function that is defined from a string. the function is assumed to be in this file Parameters ========== return a function from globals based on a name string """ env = globals() if function_name in env: return env[function_name] return None
# Timestamps
[docs]def get_timestamp(item_date, item_time=None, jitter_days=None, format=None): """ Get_timestamp will return (default) a UTC timestamp. This will have some date and (optional) time. A different format can be provided to change default behavior. eg: "%Y%m%d" """ if format is None: format = "%Y-%m-%dT%H:%M:%SZ" if item_date in ["", None]: bot.warning("No date in header, cannot create timestamp.") return None item_time = item_time or "" try: timestamp = dateutil.parser.parse("%s%s" % (item_date, item_time)) except (dateutil.parser.ParserError, OverflowError): timestamp = datetime.strptime("%s%s" % (item_date, item_time), format) if jitter_days is not None: jitter_days = int(float(jitter_days)) timestamp = timestamp + timedelta(days=jitter_days) return timestamp.strftime(format)