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