:ivar root: top LNode instance in which are nodes and links stored
    :ivar srcPort: for SLICE it is port which is connected to input of SLICE node
        for CONCAT it is port which is connected to output of CONCAT
    :ivar oldSplits: list of tuples (node, edge) which should be disconnected from graph
    :ivar newSplitNode: new node which should be connected to graph

def reconnectPorts(root: LNode, srcPort: LPort,
                   oldSplits: List[Tuple[LNode, LEdge]],
                   newSplitNode: LNode):
    """
    :ivar root: top LNode instance in which are nodes and links stored
    :ivar srcPort: for SLICE it is port which is connected to input of SLICE node
        for CONCAT it is port which is connected to output of CONCAT
    :ivar oldSplits: list of tuples (node, edge) which should be disconnected from graph
    :ivar newSplitNode: new node which should be connected to graph
    """
    # sort oldSplit nodes because they are not in same order as signals on
    # ports
    mainPortSignals = list(walkSignalPorts(srcPort))
    portOrder = {p: i for i, p in enumerate(mainPortSignals)}
    isOneToN = len(newSplitNode.west) == 1

    def portSortKey(x):
        n, e = x
        if e.dstNode is n:
            return portOrder[e.src]
        elif e.srcNode is n:
            return portOrder[e.dst]
        else:
            raise ValueError("Edge not connected to split node", e, n)

    oldSplits.sort(key=portSortKey)
    newSplitPorts = [walkSignalPorts(p) for p in
                     (newSplitNode.east if isOneToN else newSplitNode.west)]

    if isOneToN:
        newMainPort = newSplitNode.west[0]
    else:
        newMainPort = newSplitNode.east[0]

    for mainPort, splitInp, (oldSplitNode, e) in zip(
            mainPortSignals,
            walkSignalPorts(newMainPort),
            oldSplits):
        assert mainPort.direction != splitInp.direction, (
            mainPort, splitInp)

        # reconnect edge from src port to split node
        assert (e.src is mainPort and e.dstNode is oldSplitNode)\
            or (e.dst is mainPort and e.srcNode is oldSplitNode), e
        e.remove()

        _newSplitPorts = [next(p) for p in newSplitPorts]
        # reconnect part from split node to other target nodes
        if oldSplitNode.name == "CONCAT":
            root.addEdge(splitInp, mainPort,
                         originObj=e.originObj)

            for oldP, newP in zip(oldSplitNode.west, _newSplitPorts):
                for e in list(oldP.incomingEdges):
                    root.addEdge(e.src, newP, originObj=e.originObj)
                    e.remove()

        elif oldSplitNode.name == "SLICE":
            root.addEdge(mainPort, splitInp,
                         originObj=e.originObj)

            for oldP, newP in zip(oldSplitNode.east, reversed(_newSplitPorts)):
                for e in list(oldP.outgoingEdges):
                    root.addEdge(newP, e.dst, originObj=e.originObj)
                    e.remove()
        else:
            raise ValueError(oldSplitNode)

        root.children.remove(oldSplitNode)