def code_dataelem(dataelem, dataset_name="ds", exclude_size=None, include_private=False): """Code lines for a single DICOM data element :arg dataelem: the DataElement instance to turn into code :arg dataset_name: variable name of the Dataset containing dataelem :arg exclude_size: if specified, values longer than this (in bytes) will only have a commented string for a value, causing a syntax error when the code is run, and thus prompting the user to remove or fix that line. :return: a string containing code to recreate the data element If the data element is a sequence, calls code_sequence """ if dataelem.VR == "SQ": return code_sequence(dataelem, dataset_name, exclude_size, include_private) # If in DICOM dictionary, set using the keyword # If not (e.g. is private element), set using add_new method have_keyword = True try: keyword = dictionary_keyword(dataelem.tag) except KeyError: have_keyword = False valuerep = repr(dataelem.value) if exclude_size: if dataelem.VR in byte_VRs and len(dataelem.value) > exclude_size: valuerep = "# XXX Array of %d bytes excluded" % len(dataelem.value) if have_keyword: format_str = "{ds_name}.{keyword} = {valuerep}" line = format_str.format(ds_name=dataset_name, keyword=keyword, valuerep=valuerep) else: format_str = "{ds_name}.add_new({tag}, '{VR}', {valuerep})" line = format_str.format(ds_name=dataset_name, tag=tag_repr(dataelem.tag), VR=dataelem.VR, valuerep=valuerep) return line
def code_sequence(dataelem, dataset_name="ds", exclude_size=None, include_private=False, name_filter=default_name_filter): """Code lines for recreating a Sequence data element :arg dataelem: the DataElement instance of the Sequence :arg dataset_name: variable name of the dataset containing the Sequence :arg exclude_size: if specified, values longer than this (in bytes) will only have a commented string for a value, causing a syntax error when the code is run, and thus prompting the user to remove or fix that line. :arg include_private: If True, private data elements will be coded. If False, private elements are skipped :arg name_filter: a callable taking a sequence name or sequence item name, and returning a shorter name for easier code reading :return: a string containing code lines to recreate a DICOM sequence """ lines = [] seq = dataelem.value seq_name = dataelem.name seq_item_name = seq_name.replace(' Sequence', '') seq_keyword = dictionary_keyword(dataelem.tag) # Create comment line to document the start of Sequence lines.append('') lines.append("# " + seq_name) # Code line to create a new Sequence object if name_filter: seq_var = name_filter(seq_keyword) lines.append(seq_var + " = Sequence()") # Code line to add the sequence to its parent lines.append(dataset_name + "." + seq_keyword + " = " + seq_var) # Code lines to add sequence items to the Sequence for i, ds in enumerate(seq): # Determine index to use. If seq item has a data element with 'Index', # use that; if one with 'Number', use that, else start at 1 index_keyword = seq_keyword.replace("Sequence", "") + "Index" number_keyword = seq_keyword.replace("Sequence", "") + "Number" if index_keyword in ds: index_str = str(getattr(ds, index_keyword)) elif number_keyword in ds: index_str = str(getattr(ds, number_keyword)) else: index_str = str(i + 1) # Code comment line to mark start of sequence item lines.append('') lines.append("# " + seq_name + ": " + seq_item_name + " " + index_str) # Determine the variable name to use for the sequence item (dataset) ds_name = seq_var.replace("_sequence", "") + index_str # Code the sequence item code_item = code_dataset(ds, ds_name, exclude_size, include_private) lines.append(code_item) # Code the line to append the item to its parent sequence lines.append(seq_var + ".append(" + ds_name + ")") # Join the lines and return a single string return line_term.join(lines)