def fix_RemoveFOVDimensionsWhenZero(ds: Dataset, log: list) -> bool:
    fixed = False
    kw = "FieldOfViewDimensions"
    Error_regex = ".*Value is zero for.*attribute.*Field.*View.*Dimension.*"
    msg = mesgtext_cc.ErrorInfo()
    idx = subfix_LookUpRegexInLog(Error_regex, log)
    if kw in ds:
        if len(idx) == 0:
            idx.append(-1)
            log.append("Error - bad value (=0) for {}".format(kw))
        tag = Dictionary.tag_for_keyword(kw)
        elem = ds[tag]
        for i in elem.value:
            if i == 0:
                fixed = True
                break
        if fixed:
            del ds[kw]
            for i in idx:
                msg.msg = log[i]
                msg.fix = "fixed by removing the attribute"
                msg1 = msg.getWholeMessage()
                log[i] = msg1
        else:
            for i in idx:
                log.pop(i)
    return fixed
def fix_PatientPositionAndPatientOrientationCodeSequencePresent(
        ds: Dataset, log: list) -> bool:
    code_kws = [
        'CodeValue', "CodeMeaning", "CodingSchemeDesignator", "LongCodeValue",
        "URNCodeValue", "CodingSchemeVersion"
    ]
    msg = mesgtext_cc.ErrorInfo()
    fixed = False
    pp = 'PatientPosition'
    posq = 'PatientOrientationCodeSequence'
    Error_regex = ".*May not be present when {} is present.*{}.*".format(
        posq, pp)
    if posq in ds:
        if pp in ds:
            seq_elem = ds[posq]
            idx = subfix_LookUpRegexInLog(Error_regex, log)
            txt = subfix_CodeSeqItem2txt(seq_elem, 0)
            if len(idx) == 0:
                idx.append(-1)
                log.append("{} = {} and {} both are present".format(
                    pp, ds[pp].value, txt))
            for i in idx:
                msg.msg = log[i]
                if len(seq_elem.value) > 0:
                    msg.fix = "kept {} but removed {}".format(txt, pp)
                    del ds[pp]
                else:
                    msg.fix = "kept {} but removed {}".format(pp, txt)
                    del ds[posq]
                log[i] = msg.getWholeMessage()
            fixed = True
    return fixed
def subfix_ReplaceSlashWithBackslash(attrib: DataElementX, log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo('General Fix -', '')
    fix = 'fixed attribute <{}> ({}) value by changing slash to backslash {} -> {}'
    if type(attrib.value) == MultiValue:
        tmp = attrib.value
    else:
        tmp = [attrib.value]
    for idx in range(0, len(tmp)):
        old_val = tmp[idx]
        if type(tmp[idx]) == str:
            tmp[idx] = tmp[idx].replace('/', '\\')
        elif type(tmp[idx]) == bytes:
            x = bytearray()
            for elem in tmp[idx]:
                if elem == ord('/'):
                    x.append(ord('\\'))
                else:
                    x.append(elem)
            tmp[idx] = bytes(x)
        if old_val != tmp[idx]:
            msg.fix = fix.format(attrib.name, idx + 1, old_val, tmp[idx])
            log.append(msg.getWholeMessage())
            fixed = True
    if type(attrib.value) != MultiValue:
        attrib.value = tmp[0]
    return fixed
def fix_VRForLongitudinalTemporalInformationModified(ds: Dataset,
                                                     log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo()
    kw = "LongitudinalTemporalInformationModified"
    Error_regex = ".*Invalid Value Representation SH \(CS Required\)" \
             ".*{}.*".format(kw)
    idx = subfix_LookUpRegexInLog(Error_regex, log)
    if len(idx) == 0:
        idx.append(-1)
        log.append("Error - bad VR for {}".format(kw))
    if kw in ds:
        tag = Dictionary.tag_for_keyword(kw)
        if ds[tag].VR == "SH":
            ds[tag].VR = "CS"
            for i in idx:
                msg.msg = log[i]
                msg.fix = "fixed by editing SH to CS"
                msg1 = msg.getWholeMessage()
                log[i] = msg1
            fixed = True
    if not fixed:
        for i in idx:
            log.pop(i)
    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 subfix_AddOrChangeAttrib(ds: Dataset, log: list, error_regexp: str,
                             fix_message: str, keyword: str, value) -> bool:
    fixed = False
    t = Dictionary.tag_for_keyword(keyword)
    if t is None:
        return False
    desc = Dictionary.dictionary_description(t)
    ErrorOccured = False
    log_l = len(log)
    for i in range(0, log_l):
        if re.match(error_regexp, log[i]) is not None:
            msg = mesgtext_cc.ErrorInfo(log[i], fix_message)
            log[i] = msg.getWholeMessage()
            ErrorOccured = True
    if ErrorOccured:
        if keyword in ds:
            ds[keyword].value = value  # just modify
            fixed = True
        else:
            vr = Dictionary.dictionary_VR(t)
            vm = 1
            elem = DataElementX(t, vr, value)
            ds[keyword] = elem
            fixed = True
    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 fix_ReferencedImageSequence(ds, log: list) -> bool:
    # This patch is a prticular fixing procedure to replace SOPInstanceUID
    # with ReferencedSOPInstanceUID and SOPClassUID with ReferencedSOPClassUID
    fixed = False
    kw = 'ReferencedImageSequence'
    tg = Dictionary.tag_for_keyword(kw)
    if tg not in ds:
        return True
    val = ds[tg].value
    ref_cls_kw = 'ReferencedSOPClassUID'
    ref_cls_tg = Dictionary.tag_for_keyword(ref_cls_kw)
    ref_inst_kw = 'ReferencedSOPInstanceUID'
    ref_inst_tg = Dictionary.tag_for_keyword(ref_inst_kw)

    i = 0
    while i < len(val):
        item = val[i]
        if 'SOPInstanceUID' in item:
            msg = mesgtext_cc.ErrorInfo()
            msg.msg = "Item {}/{} in <ReferencedImageSequence> holds "\
                "<SOPInstanceUID> instead of <ReferencedSOPInstanceUID>".format(i + 1, len(val))
            msg.fix = "fixed by changing the attribute into <ReferencedSOPInstanceUID>"
            log.append(msg.getWholeMessage())
            item[ref_inst_tg] = DataElementX(ref_inst_tg, 'UI',
                                             item['SOPInstanceUID'].value)
            del item['SOPInstanceUID']
            fixed = True
        if 'SOPClassUID' in item:
            msg = mesgtext_cc.ErrorInfo()
            msg.msg = "Item {}/{} in <ReferencedImageSequence> holds "\
                "<SOPClassUID> instead of <ReferencedSOPClassUID>".format(i + 1, len(val))
            msg.fix = "fixed by changing the attribute into <ReferencedSOPClassUID>"
            log.append(msg.getWholeMessage())
            item[ref_cls_tg] = DataElementX(ref_cls_tg, 'UI',
                                            item['SOPClassUID'].value)
            del item['SOPClassUID']
            fixed = True
        i += 1
    return fixed
def fix_PatientSex(ds: Dataset, log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo()
    kw = "PatientSex"
    error_regex = r".*Unrecognized enumerated value .* for .* of attribute .*Patient.*Sex"
    if kw in ds:
        old_value = ds[kw].value
    else:
        old_value = ''
    new_value = ""
    fix_m = "fixed by modifying the {} from {} to empty string".format(
        kw, old_value)
    return subfix_AddOrChangeAttrib(ds, log, error_regex, fix_m, kw, new_value)
def subfix_RemoveAttrib(ds: Dataset, log: list, error_regexp: str,
                        keyword: str) -> bool:
    fixed = False
    t = Dictionary.tag_for_keyword(keyword)
    if t is None:
        return False
    desc = Dictionary.dictionary_description(t)
    ErrorOccured = False
    log_l = len(log)
    for i in range(0, log_l):
        if re.match(error_regexp, log[i]) is not None:
            msg = mesgtext_cc.ErrorInfo(log[i],
                                        "fixed by removing the attribute")
            log[i] = msg.getWholeMessage()
            ErrorOccured = True
    if ErrorOccured:
        del ds[keyword]
        fixed = True
    return fixed
def generalfix_CT_RescaleType(ds, log):
    fixed = False
    modality = None if "Modality" not in ds else ds['Modality'].value
    if modality == 'CT':
        if 'RescaleType' not in ds:
            return fixed
        if ds['RescaleType'] == 'HU':
            return fixed
        contains_localizer = False
        ImageType_v = [] if 'ImageType' not in ds else ds['ImageType'].value
        for i in ImageType_v:
            if i == 'LOCALIZER':
                contains_localizer = True
                break
        if not contains_localizer:
            oldval = ds['RescaleType'].value
            ds['RescaleType'].value = "HU"
            msg = mesgtext_cc.ErrorInfo()
            msg.msg = "General Fix - <RescaletType> is not HU (Hounsfield Units) "
            msg.fix = "fixed by changing the attribute from {} to {}".format(
                oldval, 'HU')
            log.append(msg.getWholeMessage())
            fixed = True
    return fixed
def fix_PregnancyStatus(ds: Dataset, log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo()
    kw = "PregnancyStatus"
    error_regex = r".*Unrecognized enumerated value .* attribute .*Pregnancy.*Status.*"
    return subfix_RemoveAttrib(ds, log, error_regex, kw)
def subfix_checkandfixBasicCodeSeq(seqelem: DataElementX, log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo("General Fix - Remove empty code seq ")
    items_to_be_deleted = []
    text_fun = lambda ds, att: '{}: <{}>\t'.format(att, ds[att].value)
    subfix_UpdateSRTCodes(seqelem, log)
    for i, item in enumerate(seqelem.value, 1):
        hasCodeValue = True if "CodeValue" in item else False
        emptyCodeValue = True if not hasCodeValue else item[
            "CodeValue"].is_empty
        textCodeValue = '' if not hasCodeValue else text_fun(item, "CodeValue")
        hasCodeMeaning = True if "CodeMeaning" in item else False
        emptyCodeMeaning = True if not hasCodeMeaning else item[
            "CodeMeaning"].is_empty
        textCodeMeaning = '' if not hasCodeMeaning else text_fun(
            item, "CodeMeaning")
        hasLongCodeValue = True if "LongCodeValue" in item else False
        emptyLongCodeValue = True if not hasLongCodeValue else item[
            "LongCodeValue"].is_empty
        textLongCodeValue = '' if not hasLongCodeValue else text_fun(
            item, "LongCodeValue")
        hasURNCodeValue = True if "URNCodeValue" in item else False
        emptyURNCodeValue = True if not hasURNCodeValue else item[
            "CodURNCodeValue"].is_empty
        textURNCodeValue = '' if not hasURNCodeValue else text_fun(
            item, "CodURNCodeValue")
        hasCodingSchemeDesignator = True if "CodingSchemeDesignator" in item else False
        emptyCodingSchemeDesignator = True if not hasCodingSchemeDesignator else item[
            "CodingSchemeDesignator"].is_empty
        textCodingSchemeDesignator = '' if not hasCodingSchemeDesignator else text_fun(
            item, "CodingSchemeDesignator")
        hasCodingSchemeVersion = True if "CodingSchemeVersion" in item else False
        emptyCodingSchemeVersion = True if not hasCodingSchemeVersion else item[
            "CodingSchemeVersion"].is_empty
        textCodingSchemeVersion = '' if not hasCodingSchemeVersion else text_fun(
            item, "CodingSchemeVersion")
        hasCodeValue = hasCodeValue or hasLongCodeValue or hasURNCodeValue
        emptyCodeValue = not (not emptyCodeValue or not emptyLongCodeValue
                              or not emptyURNCodeValue)
        textCodeValue = (textCodeValue + textLongCodeValue + textURNCodeValue)
        bit_code = numpy.uint8(0)
        if emptyCodeValue:
            bit_code = bit_code | 0x1
        if emptyCodeMeaning:
            bit_code = bit_code | 0x10
        if emptyCodingSchemeDesignator:
            bit_code = bit_code | 0x100
        state_text = subfix_CodeSeqItem2txt(seqelem, i - 1)
        state_text = ". Item current value is: " + state_text if state_text != '' else ''
        if hasCodingSchemeVersion and emptyCodingSchemeVersion:
            del item["CodingSchemeVersion"]
            msg.fix = "Empty CodingSchemeVersion in item {} of {} was deleted".format(
                i, seqelem.name) + state_text
            del_msg = msg.getWholeMessage()
            log.append(del_msg)
        if bit_code == 0x111 or bit_code == 0x110 or bit_code == 0x011 or \
            bit_code == 0x101 or bit_code == 0x001 or bit_code == 0x010:
            items_to_be_deleted.append(item)
            msg.fix = "Item {} of {} was deleted".format(i, seqelem.keyword)
            del_msg = msg.getWholeMessage()
            log.append(del_msg)
            fixed = True
        if bit_code == 0x100:
            if hasCodingSchemeDesignator:
                item["CodingSchemeDesignator"].value = '99LOCAL'
                msg.fix = "The value for CodingSchemeDesignator in "\
                        "item {} of {} was modified to 99LOCAL".format(
                        i, seqelem.keyword
                  ) + state_text
                del_msg = msg.getWholeMessage()
                log.append(del_msg)
            else:
                kw = "CodingSchemeDesignator"
                new_tag = Dictionary.tag_for_keyword(kw)
                new_vr = Dictionary.dictionary_VR(new_tag)
                new_elem = DataElementX(new_tag, new_vr, "99LOCAL")
                item[kw] = new_elem
                msg.fix = "An element of CodingSchemeDesignator with value "\
                        "<99LOCAL> in item {} of {} was added".format(
                        i, seqelem.keyword
                  ) + state_text
                del_msg = msg.getWholeMessage()
                log.append(del_msg)
            fixed = True
    for el in items_to_be_deleted:
        seqelem.value.remove(el)
def subfix_UpdateSRTCodes(seqelem: DataElementX, log: list) -> bool:
    fixed = False
    msg = mesgtext_cc.ErrorInfo(
        "General Fix - Upadate old snomed codes to SCT")
    items_to_be_deleted = []
    text_fun = lambda ds, att: '{}: {}\t'.format(att, ds[att])
    for i, item in enumerate(seqelem.value, 1):
        hasCodeValue = True if "CodeValue" in item else False
        emptyCodeValue = True if not hasCodeValue else item[
            "CodeValue"].is_empty
        textCodeValue = '' if not hasCodeValue else text_fun(item, "CodeValue")
        hasCodeMeaning = True if "CodeMeaning" in item else False
        emptyCodeMeaning = True if not hasCodeMeaning else item[
            "CodeMeaning"].is_empty
        textCodeMeaning = '' if not hasCodeMeaning else text_fun(
            item, "CodeMeaning")
        hasLongCodeValue = True if "LongCodeValue" in item else False
        emptyLongCodeValue = True if not hasLongCodeValue else item[
            "LongCodeValue"].is_empty
        textLongCodeValue = '' if not hasLongCodeValue else text_fun(
            item, "LongCodeValue")
        hasURNCodeValue = True if "URNCodeValue" in item else False
        emptyURNCodeValue = True if not hasURNCodeValue else item[
            "CodURNCodeValue"].is_empty
        textURNCodeValue = '' if not hasURNCodeValue else text_fun(
            item, "CodURNCodeValue")
        hasCodingSchemeDesignator = True if "CodingSchemeDesignator" in item else False
        emptyCodingSchemeDesignator = True if not hasCodingSchemeDesignator else item[
            "CodingSchemeDesignator"].is_empty
        textCodingSchemeDesignator = '' if not hasCodingSchemeDesignator else text_fun(
            item, "CodingSchemeDesignator")
        hasCodingSchemeVersion = True if "CodingSchemeVersion" in item else False
        emptyCodingSchemeVersion = True if not hasCodingSchemeVersion else item[
            "CodingSchemeVersion"].is_empty
        textCodingSchemeVersion = '' if not hasCodingSchemeVersion else text_fun(
            item, "CodingSchemeVersion")
        hasCodeValue = hasCodeValue or hasLongCodeValue or hasURNCodeValue
        emptyCodeValue = not (not emptyCodeValue or not emptyLongCodeValue
                              or not emptyURNCodeValue)
        textCodeValue = (textCodeValue + textLongCodeValue + textURNCodeValue)
        bit_code = numpy.uint8(0)
        if emptyCodeValue:
            bit_code = bit_code | 0x1
        if emptyCodeMeaning:
            bit_code = bit_code | 0x10
        if emptyCodingSchemeDesignator:
            bit_code = bit_code | 0x100
        state_text = subfix_CodeSeqItem2txt(seqelem, i - 1)
        isSRT = False
        if hasCodingSchemeDesignator:
            v = item["CodingSchemeDesignator"].value
            if v == "SNM3" or v == "99SDM" or v == "SRT":
                isSRT = True
        else:
            if hasCodeValue:
                v = item["CodeValue"].value
                if re.match("[A-Z][A-Z0-9]{0,2}-[0-9A-Z]{4,5}", v) is not None:
                    isSRT = True
        if not isSRT or not hasCodeValue:
            return False
        value = item["CodeValue"].value
        first_dict = srt.mapping['SRT']
        second_dict = sctsrt.replaced_entries
        replacing_value = ''
        if value in first_dict:
            replacing_value = first_dict[value]
        elif value in second_dict:
            replacingvalue = second_dict[value]
        if len(replacing_value) == 0:
            return False
        replacing_meaning = ''
        if replacing_value in sctsrt.sct_meaning:
            replacing_meaning = sctsrt.sct_meaning[replacing_value]
        msg1 = "item {} of {}:\t".format(i, seqelem.keyword)
        msg1 += "({}-{})".format(i, 1) + subfix_UpdateOrInsertCodeAttribute(
            seqelem, i - 1, "CodeValue", replacing_value)
        msg1 += "({}-{})".format(i, 2) + subfix_UpdateOrInsertCodeAttribute(
            seqelem, i - 1, "CodeMeaning", replacing_meaning)
        msg1 += "({}-{})".format(i, 3) + subfix_UpdateOrInsertCodeAttribute(
            seqelem, i - 1, "CodingSchemeDesignator", 'SCT')
        msg.fix = msg1
        msg2 = msg.getWholeMessage()
        log.append(msg2)
        fixed = True
    return fixed