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:
                msg = mesgtext_cc.ErrorInfo("<{}> {}".format(
                    a.description(), validate_vr.tag2str(a.tag)))
                err = "<{}> {}".format(a.description(),
                                       validate_vr.tag2str(a.tag))
                msg = mesgtext_cc.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 subfix_ReplaceSlashWithBackslash(attrib: DataElement, 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 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 = DataElement(t, vr, value)
            ds[keyword] = elem
            fixed = True
    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
    return fixed
def generalfix_RemoveUnwanterPixelAspctRatio(ds: Dataset, log: list) -> bool:
    fixed = False
    kw = "PixelAspectRatio"
    is_one_to_one = False
    if kw in ds:
        elem = ds[kw]
        if type(elem) == MultiValue:
            if len(elem) == 2:
                is_one_to_one = (elem.value[0] == elem.value[2])
        if (Condition_UnwantedPixelAspectRatioWhenPixelSpacingPresent(
                ds, ds, ds
        ) or Condition_UnwantedPixelAspectRatioWhenImagerPixelSpacingPresent(
                ds, ds, ds
        ) or Condition_UnwantedPixelAspectRatioWhenNominalScannedPixelSpacingPresent(
                ds, ds, ds
        ) or Condition_UnwantedPixelAspectRatioWhenSharedPixelMeasuresMacro(
                ds, ds, ds
        ) or Condition_UnwantedPixelAspectRatioWhenPerFramePixelMeasuresMacro(
                ds, ds, ds) or
                Condition_UnwantedPixelAspectRatioWhenMPEG2MPHLTransferSyntax(
                    ds, ds, ds) or is_one_to_one):
            msg = mesgtext_cc.ErrorInfo()
            msg.msg = '{} Error - {}'.format(
                ErrorType.BadValue.value,
                "<PixelAspectRatio> is 1:1 or redundant")
            msg.fix = "fixed by removing the attribute"
            log.append(msg.getWholeMessage())
            del ds["PixelAspectRatio"]
            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.DataElement_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 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 priorfix_RemoveIllegalTags(ds: Dataset, parent_kw: str, log: list) -> bool:
    tags_to_be_removed = []
    fixed = False
    for k, a in ds.items():
        try:
            a = ds[k]
        except KeyError as err:
            if not k.is_private:
                if not Dictionary.dictionary_has_tag(k):
                    ttaagg = validate_vr.tag2str(a.tag)
                    eerr = mesgtext_cc.ErrorInfo(
                        "General Fix - tag {} in {}is not a standard dicom tag"
                        .format(ttaagg,
                                parent_kw), 'fixed by removing the attribute')
                    log.append(eerr.getWholeMessage())
                    tags_to_be_removed.append(a.tag)
                    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_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 len(idx) == 0:
        idx.append(-1)
        log.append("Error - bad value (=0) for {}".format(kw))
    if kw in ds:
        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
    return fixed
def fix_BitsAllocated8ToBitsAllocated16(ds: Dataset, log: list):
    log_l = len(log)
    ErrorPattern = "Error - Unrecognized enumerated value <{}> for value 1 of " \
    "attribute {} BinaryValueDescription_BitsAre{}"

    convert = False
    for i in range(0, log_l):
        if log[i] == ErrorPattern.format(8, "Bits Allocated", 16) or\
                log[i] == ErrorPattern.format(8, "Bits Stored", 16) or\
                log[i] == ErrorPattern.format(7, "High Bit", 15) :
            x = "fixed by conversion of PixelData to 16 bits"
            msg = mesgtext_cc.ErrorInfo(log[i], x)
            log[i] += msg.getWholeMessage()
            convert = True
    if convert:
        subfix_ConvertImageData16(ds, log)
def subfix_checkandfixBasicCodeSeq(seqelem: DataElement, 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"] = '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 = DataElement(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: DataElement, 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