def generalfix_VM1(ds, log): fixed = False elemsTobeCorrected = [] for key, a in ds.items(): a = ds[key] if key.is_private: continue try: dvr = dictionary_VM(key) except (BaseException): return fixed if dvr != '1': continue if a.VM <= 1: continue if (a.VR != 'LT' or a.VR != 'LO'): continue concat = '/'.join(a.value) ds[key] = DataElementX(key, a.VR, concat) fixed = True err = "<{}> {}".format(a.keyword, validate_vr.tag2str(a.tag)) msg = ErrorInfo( "General Fix - Value Multiplicity for {} "\ "is not allowed to be more than one".format(err), "fixed by concatenating all itmes into one {}".format(concat)) log.append(msg.getWholeMessage()) fixed = True return fixed
def generalfix_TrailingNulls(ds: Dataset, log: list) -> bool: fixed = False elemsTobeCorrected = [] for key, a in ds.items(): a = ds[key] if key.is_private: continue if a.VR == 'UI' or a.VR == 'OB' or a.VR == 'OW' or a.VR == 'UN': continue if type(a) == pydicom.dataelem.RawDataElement: a = pydicom.dataelem.DataElement_from_raw(a) if type(a.value) == Sequence: for item in a.value: fixed = fixed or generalfix_TrailingNulls(item, log) elif type(a.value) == Dataset: fixed = fixed or generalfix_TrailingNulls(a.value, log) else: partial_fixed = subfix_HasTrailingNulls(a) if partial_fixed: err = "<{}> {}".format(a.keyword, validate_vr.tag2str(a.tag)) msg = ErrorInfo( "General Fix - Trailing null bytesz", "fixed by removing the trailing null bytes for {}".format( err)) log.append(msg.getWholeMessage()) elemsTobeCorrected.append(a) fixed = True return fixed
def LoopOverAllAtribsAndRemoveIfConditionIsTrue(ds: Dataset, cond, log: list, err='') -> bool: fixed = False elements_to_be_removed = [] for key, a in ds.items(): a = ds[key] if type(a) == pydicom.dataelem.RawDataElement: a = pydicom.dataelem.DataElementX_from_raw(a) if type(a.value) == Sequence: for item in a.value: fixed = fixed or LoopOverAllAtribsAndRemoveIfConditionIsTrue( item, cond, log, err) elif type(a.value) == Dataset: fixed = fixed or LoopOverAllAtribsAndRemoveIfConditionIsTrue( a.value, cond, log, err) else: if cond(a): ttaagg = validate_vr.tag2str(a.tag) attrib = "<{}> -> {}".format(a.keyword, ttaagg) tmperr = err.format(attrib) msg = mesgtext_cc.ErrorInfo() msg.msg = tmperr msg.fix = "fixed by removing the attribute" log.append(msg.getWholeMessage()) fixed = True elements_to_be_removed.append(a.tag) for tg in elements_to_be_removed: del ds[tg] return fixed
def priorfix_RemoveIllegalTags(ds: Dataset, parent_kw: str, log: list) -> bool: logger = logging.getLogger(__name__) tags_to_be_removed = [] fixed = False for k, a in ds.items(): try: a = ds[k] except BaseException as err: ttaagg = validate_vr.tag2str(k) eerr = mesgtext_cc.ErrorInfo( "General Fix - attribute with tag {} in {} is not" " readable by pydicom".format(ttaagg, parent_kw), 'fixed by removing the attribute') log.append(eerr.getWholeMessage()) loggermsg = 'attribute with tag {} in {} is not '\ 'readable by pydicom because {}'.format(ttaagg, parent_kw, err) logger.error(loggermsg, stack_info=True) tags_to_be_removed.append(k) continue if type(a.value) == Sequence: for item in a.value: fixed = fixed or priorfix_RemoveIllegalTags( item, a.keyword, log) elif type(a.value) == Dataset: fixed = fixed or priorfix_RemoveIllegalTags( a.value, a.keyword, log) for tg in tags_to_be_removed: del ds[tg] return fixed
def generalfix_RemoveEmptyCodes(parent_ds: Dataset, log: list, kw_to_be_removed: list = []) -> bool: global iod_dict if 'SOPClassUID' in parent_ds: iod_dict = get_full_attrib_list(parent_ds) fixed = False for key, elem in parent_ds.items(): elem = parent_ds[key] if type(elem) == pydicom.dataelem.RawDataElement: elem = pydicom.dataelem.DataElement_from_raw(elem) if type(elem.value) == Sequence: if elem.keyword.endswith("CodeSequence"): if iod_dict is None or elem.keyword not in iod_dict: type_ = None else: type_ = iod_dict[elem.keyword][0]['type'] if type_ != '1' or type_ != '1C' or type_ != '2'\ or type_ != '2C': fixed = fixed or subfix_checkandfixBasicCodeSeq(elem, log) if elem.is_empty: kw_to_be_removed.append((parent_ds, elem.keyword)) else: for (item, idx) in zip(elem.value, range(0, len(elem.value))): fixed = fixed or generalfix_RemoveEmptyCodes( item, log, kw_to_be_removed) elif type(elem.value) == Dataset: fixed = fixed or generalfix_RemoveEmptyCodes( elem.value, log, kw_to_be_removed, ) if 'SOPClassUID' in parent_ds: for ddss, k in kw_to_be_removed: if k in ddss: a = ddss[k] # print('{} is present and going to be removed'.format(k)) else: # print('{} is not present and going to continue anyway'.format(k)) continue if iod_dict is None or k not in iod_dict: type_ = None else: type_ = iod_dict[k][0]['type'] if type_ != '1' or type_ != '1C' or type_ != '2' or type_ != '2C': err = "{} <{}>".format(validate_vr.tag2str(a.tag), a.keyword) msg = ErrorInfo( "General Fix - Attribute type SQ has no items", "fixed by removing the whole attribute for {}".format(err)) log.append(msg.getWholeMessage()) del ddss[k]
def check(v, n, N, a): u = v.upper() if u != v: err = "<{}> {}".format(a.keyword, validate_vr.tag2str(a.tag)) msg = ErrorInfo( "General Fix - {} lower case is not allowed for Code "\ "String itme number {}/ {}".format(err, n, N), "fixed by capitalizing the value from {} to {}".format( v, u)) log.append(msg.getWholeMessage()) return u else: return None
def generalfix_WindowWidth(ds, log): fixed = False wwkw = 'WindowWidth' wwtg = tag_for_keyword(wwkw) if wwtg in ds: if ds[wwtg].value == 0: ds[wwtg].value = 1 err = "<{}> {}".format(wwkw, validate_vr.tag2str(wwtg)) msg = ErrorInfo( "General Fix - Window width {} "\ "is not allowed to be 0".format(err), "fixed by replacing it with 1") log.append(msg.getWholeMessage()) fixed = True return fixed
def generalfix_RealWorldValueMappingSequence(ds, log): kw = 'RealWorldValueMappingSequence' tg = tag_for_keyword(kw) if tg in ds: v = ds[tg].value for i, item in enumerate(v): in_key = 'LUTLabel' in_tg = tag_for_keyword(in_key) if in_tg not in item: new_el = DataElementX(in_tg, 'SH', 'Unknown') item[in_tg] = new_el err = "<{}> {}".format(in_key, validate_vr.tag2str(in_tg)) msg = ErrorInfo( "General Fix - The item number {} lacks {}".format(i, err), "fixed by adding a new element with value <{}>".format( new_el.value)) log.append(msg.getWholeMessage())
def check(v, n, N, a): v = str(v) if len(v) > 16: f = float(v) u = '{:1.10E}'.format(f) n = 10 while len(u) > 16 and n > 0: n -= 1 ptrn = '{{:1.{}E}}'.format(n) u = ptrn.format(f) err = "<{}> {}".format(a.keyword, validate_vr.tag2str(a.tag)) msg = ErrorInfo( "General Fix - {} value length greater than 16 is not allowed"\ "for DS value representation in itme number {}/ {}".format( err, n, N), "fixed by modifying the precision from {} to {}".format( v, u)) log.append(msg.getWholeMessage()) return u else: return None
def subfix_FindAndReplaceAttribValue(find_regex: str, replace: str, ds: Dataset, ttag: Tag, group=0, verbose=False): replaced_global = False changed_element_lists = [] for key, elem in ds.items(): elem = ds[key] i_count = 0 if type(elem.value) == Sequence: for item in elem.value: replaced_local = subfix_FindAndReplaceAttribValue( find_regex, replace, item, ttag, group, verbose) if replaced_local: replaced_global = True i_count += 1 elif type(elem.value) == Dataset: print("dataset {} from {}".format('', elem.keyword)) replaced_local = subfix_FindAndReplaceAttribValue( find_regex, replace, elem.value, ttag, group, verbose) replaced_global = replaced_global or replaced_local else: if ttag is not None: if elem.tag != ttag: continue if type(elem) == pydicom.dataelem.RawDataElement: elem = pydicom.dataelem.DataElementX_from_raw(elem) if type(elem.value) == MultiValue: v = elem.value else: v = [elem.value] replaced_items = [] for txt, idx in zip(v, range(0, len(v))): if type(txt) == str: r = ReplaceRegex(find_regex, replace, txt) if txt != r: replaced_items.append((idx, r)) if type(elem.value) == MultiValue: for idx, replaced_txt in replaced_items: if verbose: t = validate_vr.tag2str(elem.tag) msg = '--->{}[{}] is {} which is replaced by {}'.format( t, idx, elem.value[idx], replaced_txt) print(msg) elem.value[idx] = replaced_txt replaced_global = True elif len(replaced_items) != 0: if verbose: t = validate_vr.tag2str(elem.tag) msg = '--->{} is {} which is replaced by {}'.format( t, elem.value, replaced_items[0][1]) print(msg) elem.value = replaced_items[0][1] replaced_global = True if len(replaced_items) != 0: changed_element_lists.append(elem) for el in changed_element_lists: del ds[el.tag] ds[el.tag] = el return replaced_global