def mergeVariants(variants):

    if len(variants) == 0:
        return []

    # sorts by start and then end
    variants.sort()
    merged_variants = []

    def _add(offset, dest, src):
        for x, c in enumerate(src):
            dest[x + offset] = c

    def _split(seq0, seq1):
        # split
        was_0, was_1 = seq0[0] == "-", seq1[0] == "-"
        for x, cc in enumerate(zip(seq0, seq1)):
            is_0, is_1 = cc[0] == "-", cc[1] == "-"
            # yield all changes
            if (is_0 ^ was_0) or (is_1 ^ was_1):
                yield x, was_0, was_1
            was_0, was_1 = is_0, is_1

        yield x + 1, was_0, was_1

    last = variants[0]
    for this in variants[1:]:

        if this.start < last.end and \
                this.action == "-" and \
                last.action == "-":

            E.warn("merging overlapping deletions: %s and %s" %
                   (str(last), str(this)))

            mend = max(last.end, this.end)
            mstart = min(this.start, last.start)
            l = mend - mstart

            seq0 = list("-" * l)
            seq1 = list("-" * l)

            _add(last.start - mstart, seq0, last.variantseqs[0])
            _add(last.start - mstart, seq1, last.variantseqs[1])
            _add(this.start - mstart, seq0, this.variantseqs[0])
            _add(this.start - mstart, seq1, this.variantseqs[1])

            last_x = 0
            n = []
            for x, was_0, was_1 in _split(seq0, seq1):
                if last_x == x:
                    continue

                this = ExtendedVariant._make((mstart + last_x,
                                              mstart + x,
                                              "*",
                                              last.action,
                                              was_0 ^ was_1,
                                              ["".join(seq0[last_x:x]),
                                               "".join(seq1[last_x:x])],
                                              ))
                n.append(this)
                last_x = x

            E.warn("overlapping deletions merged in %i blocks as: %s" %
                   (len(n), map(str, n)))
            merged_variants.extend(n[:-1])
            this = n[-1]
        else:
            merged_variants.append(last)

        last = this

    merged_variants.append(last)

    return merged_variants
merge overlapping variants.
dataset/ETHPy150Open CGATOxford/cgat/CGAT/Variants.py/mergeVariants