예제 #1
0
def _render_parasite_branches(fig: plot_tools.FigureWrapper, node: tree.Node,
                              recon_obj: recon.Reconciliation,
                              host_lookup: dict, parasite_lookup: dict):
    """
    Very basic branch drawing
    :param fig: Figure object that visualizes trees using MatplotLib
    :param node: Node object representing the parasite event being rendered
    :param recon_obj: Reconciliation object that represents an edge-to-edge mapping from  a parasite tree to a host tree
    :param host_lookup: Dictionary with host node names as the key and host node objects as the values
    :param parasite_lookup: Dictionary with parasite node names as the key and parasite node objects as the values
    """
    node_pos = plot_tools.Position(node.layout.x, node.layout.y)

    left_node, right_node = _get_children(node, recon_obj, parasite_lookup)

    right_pos = plot_tools.Position(right_node.layout.x, right_node.layout.y)

    mapping_node = recon_obj.mapping_of(node.name)
    event = recon_obj.event_of(mapping_node)

    if event.event_type is recon.EventType.COSPECIATION:
        _render_cospeciation_branch(node, host_lookup, parasite_lookup,
                                    recon_obj, fig)
    elif event.event_type is recon.EventType.DUPLICATION:
        _connect_children(node, host_lookup, parasite_lookup, recon_obj, fig)
    elif event.event_type is recon.EventType.TRANSFER:
        _render_transfer_branch(node_pos, right_pos, fig, node, host_lookup,
                                recon_obj, right_node)
        _connect_child_to_parent(node, left_node, host_lookup, recon_obj, fig)
    else:
        raise ValueError('%s is not an known event type' % event.event_type)
예제 #2
0
def _connect_child_to_parent(node: tree.Node,
                             child_node: tree.Node,
                             host_lookup: dict,
                             recon_obj: recon.Reconciliation,
                             fig: plot_tools.FigureWrapper,
                             stop_row: float = None):
    """
    Connects a child node to its parent node
    :param node: Node object representing a parasite event
    :param child_node: The child node object of a given node
    :param host_lookup: Dictionary with host node names as the key and host node objects as the values
    :param recon_obj: Reconciliation object that represents an edge-to-edge mapping from  a parasite tree to a host tree
    :param fig: Figure object that visualizes trees using MatplotLib
    :param stop_row: row number to stop line drawing on
    """
    mapping_node = recon_obj.mapping_of(child_node.name)
    host_node = host_lookup[mapping_node.host]

    if stop_row == None:
        stop_row = node.layout.row

    current_pos = plot_tools.Position(child_node.layout.x, child_node.layout.y)

    while host_node.layout.row != stop_row and host_node.parent_node:
        parent_node = host_node.parent_node
        if parent_node.layout.row < host_node.layout.row:
            v_track = parent_node.get_and_update_track(
                tree.Track.UPPER_VERTICAL)
        else:
            v_track = parent_node.get_and_update_track(
                tree.Track.LOWER_VERTICAL)
            while v_track < parent_node.layout.upper_v_track:
                v_track = parent_node.get_and_update_track(
                    tree.Track.LOWER_VERTICAL)
        h_track = parent_node.get_and_update_track(tree.Track.HORIZONTAL)
        offset = parent_node.layout.offset

        sub_parent_pos = plot_tools.Position(parent_node.layout.x - (offset * v_track), \
            parent_node.layout.y + (offset * h_track))

        _render_loss_branch(sub_parent_pos, current_pos, fig)

        host_node = parent_node
        current_pos = sub_parent_pos

    node_pos = plot_tools.Position(node.layout.x, node.layout.y)
    mid_pos = plot_tools.Position(node_pos.x, current_pos.y)

    fig.line(node_pos, mid_pos, render_settings.PARASITE_EDGE_COLOR)
    fig.line(mid_pos, current_pos, render_settings.PARASITE_EDGE_COLOR)
예제 #3
0
def _render_transfer_branch(node_pos: plot_tools.Position,
                            right_pos: plot_tools.Position,
                            fig: plot_tools.FigureWrapper, node: tree.Node,
                            host_lookup: dict, recon_obj: recon.Reconciliation,
                            right_node: tree.Node):
    """
    Renders a transfer branch
    :param node_xy: x and y position of a node
    :param right_pos: x and y position of the right child of a node
    :param fig: Figure object that visualizes trees using MatplotLib
    :param node: Node object representing the parasite event being rendered
    :param host_lookup: Dictionary with host node names as the key and host node objects as the values
    :param recon_obj: Reconciliation object that represents an edge-to-edge mapping from  a parasite tree to a host tree
    :param right_node: The right node object of node
    """

    child_mapping_node = recon_obj.mapping_of(right_node.name)
    child_host_node = host_lookup[child_mapping_node.host]

    # Check temporal consistency of transfer event
    if child_host_node.parent_node.layout.col < node.layout.col:
        # Draw right node, which is transfered
        mid_pos = plot_tools.Position(node_pos.x,
                                      right_pos.y)  # xy coords of midpoint
        y_midpoint = abs(
            mid_pos.y +
            node_pos.y) / 2  # value of midpoint between mid_xy and parent node

        # Determine if transfer is upwards or downwards, and draw triangle accordingly
        is_upwards = True if y_midpoint < mid_pos.y else False
        arrow_pos = plot_tools.Position(node_pos.x, y_midpoint)
        if is_upwards:
            fig.triangle(arrow_pos, render_settings.PARASITE_EDGE_COLOR)
        else:
            fig.triangle(arrow_pos,
                         render_settings.PARASITE_EDGE_COLOR,
                         rotation=render_settings.DOWN_ARROW_ROTATION)

        # Draw branch to midpoint, then draw branch to child
        fig.line(node_pos, mid_pos, render_settings.PARASITE_EDGE_COLOR)
        fig.line(mid_pos, right_pos, render_settings.PARASITE_EDGE_COLOR)
    else:
        transfer_edge_color = plot_tools.transparent_color(
            render_settings.PARASITE_EDGE_COLOR,
            render_settings.TRANSFER_TRANSPARENCY)
        fig.arrow_segment(node_pos, right_pos, transfer_edge_color)
        fig.line(node_pos, right_pos, transfer_edge_color)
예제 #4
0
def _render_host_helper(fig: plot_tools.FigureWrapper, node: tree.Node,
                        show_internal_labels: bool, font_size: float,
                        host_tree: tree.Tree):
    """
    Helper function for rendering the host tree.
    :param fig: Figure object that visualizes trees using MatplotLib
    :param node: Host Node object that will be rendered
    :param show_internal_labels: Boolean that determines whether or not the internal labels are shown
    :param font_size: Font size for the text of the tips and internal nodes of the tree
    :param host_tree: Tree object representing a Host Tree
    """
    host_tree.pos_dict[(node.layout.row, node.layout.col)] = node

    node_pos = plot_tools.Position(node.layout.x, node.layout.y)

    if node.is_leaf():
        text_offset = (node_pos.x + render_settings.TIP_TEXT_OFFSET_X,
                       node_pos.y)
        if node.layout.node_count == 0:
            fig.text_v2(text_offset,
                        node.name,
                        render_settings.HOST_NODE_COLOR,
                        size=font_size,
                        vertical_alignment=render_settings.TIP_ALIGNMENT)
        else:
            fig.text_v2(text_offset,
                        node.name,
                        render_settings.HOST_NODE_COLOR,
                        size=font_size,
                        vertical_alignment=render_settings.TIP_ALIGNMENT)
    else:
        fig.dot(node_pos,
                col=render_settings.HOST_NODE_COLOR)  # Render host node
        if show_internal_labels:
            color = plot_tools.transparent_color(
                render_settings.HOST_NODE_COLOR,
                render_settings.INTERNAL_NODE_ALPHA)
            text_xy = (node_pos.x, node_pos.y)
            fig.text_v2(text_xy,
                        node.name,
                        color,
                        size=font_size,
                        border_col=render_settings.HOST_NODE_BORDER_COLOR)
        left_x, left_y = node.left_node.layout.x, node.left_node.layout.y
        right_x, right_y = node.right_node.layout.x, node.right_node.layout.y
        fig.line(node_pos, (node_pos.x, left_y),
                 render_settings.HOST_EDGE_COLOR)
        fig.line(node_pos, (node_pos.x, right_y),
                 render_settings.HOST_EDGE_COLOR)
        fig.line((node_pos.x, left_y), (left_x, left_y),
                 render_settings.HOST_EDGE_COLOR)
        fig.line((node_pos.x, right_y), (right_x, right_y),
                 render_settings.HOST_EDGE_COLOR)
        _render_host_helper(fig, node.left_node, show_internal_labels,
                            font_size, host_tree)
        _render_host_helper(fig, node.right_node, show_internal_labels,
                            font_size, host_tree)
예제 #5
0
def _render_curved_line_to(node_pos: plot_tools.Position,
                           other_pos: plot_tools.Position,
                           fig: plot_tools.FigureWrapper):
    """
    Renders a curved line from one point to another
    :param node_pos: x and y position of a node
    :param other_pos: x and y position of another node
    :param fig: Figure object that visualizes trees using MatplotLib
    """
    mid_pos = plot_tools.Position(node_pos.x, other_pos.y)
    fig.line(node_pos, mid_pos, render_settings.PARASITE_EDGE_COLOR)
    fig.line(mid_pos, other_pos, render_settings.PARASITE_EDGE_COLOR)
예제 #6
0
def _render_parasite_node(fig: plot_tools.FigureWrapper,
                          node: tree.Node,
                          event: recon.Event,
                          font_size: float,
                          longest_host_name: int,
                          show_internal_labels: bool = False,
                          show_freq: bool = False):
    """
    Renders a single parasite node
    :param fig: Figure object that visualizes trees using MatplotLib
    :param node: parasite Node that will be rendered
    :param event: Event object that gives event for the given Node
    :param font_size: Font size for text
    :param show_internal_labels: Boolean that determines whether or not the internal labels are shown
    :param show_freq: Boolean that determines wheter or not the frequencies are shown
    :param longest_host_name: The number of symbols in the longest host tree tip name
    """

    node_pos = plot_tools.Position(node.layout.x, node.layout.y)
    render_color, render_shape = _event_color_shape(event)

    if node.is_leaf():
        fig.text_v2(
            (node.layout.x + render_settings.TIP_TEXT_OFFSET_X, node.layout.y),
            "-" * (3 + longest_host_name) + node.name,
            render_color,
            size=font_size,
            vertical_alignment=render_settings.TIP_ALIGNMENT)
        return

    fig.dot(node_pos, col=render_color, marker=render_shape)
    text = ''
    text_color = plot_tools.transparent_color(
        render_color, render_settings.INTERNAL_NODE_ALPHA)
    if show_internal_labels and show_freq:
        text = node.name + ', ' + _get_frequency_text(event.freq)
    elif show_internal_labels:
        text = node.name
    elif show_freq:
        if event.freq:
            text = _get_frequency_text(event.freq)
        else:
            raise RuntimeError(
                "Could not render reconciliation: show_freq is True but event.freq is None"
            )
    if text:
        fig.text_v2(node_pos,
                    text,
                    text_color,
                    size=font_size,
                    border_col=render_settings.PARASITE_NODE_BORDER_COLOR)
예제 #7
0
def _render_loss_branch(node_pos: plot_tools.Position,
                        next_pos: plot_tools.Position,
                        fig: plot_tools.FigureWrapper):
    """
    Renders a loss branch given a two positions
    :param node_pos: x and y position of a node
    :param next_pos: x and y position of another node
    :param fig: Figure object that visualizes trees using MatplotLib
    """
    # Create vertical line to next node
    mid_pos = plot_tools.Position(node_pos.x, next_pos.y)
    fig.line(node_pos,
             mid_pos,
             render_settings.LOSS_EDGE_COLOR,
             linestyle='--')
    fig.line(mid_pos, next_pos, render_settings.PARASITE_EDGE_COLOR)
예제 #8
0
def _render_cospeciation_branch(node: tree.Node, host_lookup: dict,
                                parasite_lookup: dict,
                                recon_obj: recon.Reconciliation,
                                fig: plot_tools.FigureWrapper):
    """
    Renders the cospeciation branch.
    :param node: Node object representing the parasite event being rendered
    :param host_lookup: Dictionary with host node names as the key and host node objects as the values
    :param parasite_lookup: Dictionary with parasite node names as the key and parasite node objects as the values
    :param recon_obj: Reconciliation object that represents an edge-to-edge mapping from  a parasite tree to a host tree
    :param fig: Figure object that visualizes trees using MatplotLib
    """
    left_node, right_node = _get_children(node, recon_obj, parasite_lookup)

    node_pos = plot_tools.Position(node.layout.x, node.layout.y)
    left_pos = plot_tools.Position(left_node.layout.x, left_node.layout.y)
    right_pos = plot_tools.Position(right_node.layout.x, right_node.layout.y)

    mapping_node = recon_obj.mapping_of(node.name)
    host_node = host_lookup[mapping_node.host]

    # Update h_track
    host_node.get_and_update_track(tree.Track.HORIZONTAL)

    left_mapping_node = recon_obj.mapping_of(left_node.name)
    left_host_node = host_lookup[left_mapping_node.host]

    right_mapping_node = recon_obj.mapping_of(right_node.name)
    right_host_node = host_lookup[right_mapping_node.host]
    # Draw left node
    offset = host_node.layout.offset
    if host_node.left_node.name == left_host_node.name:
        _render_curved_line_to(node_pos, left_pos, fig)
        if host_node.layout.lower_v_track < (host_node.layout.x -
                                             node_pos.x) / offset:
            host_node.layout.lower_v_track += (host_node.layout.x -
                                               node_pos.x) / offset + offset
    else:
        stop_row = host_node.left_node.layout.row
        _connect_child_to_parent(node,
                                 left_node,
                                 host_lookup,
                                 recon_obj,
                                 fig,
                                 stop_row=stop_row)

    # Draw Right node
    if host_node.right_node.name == right_host_node.name:
        _render_curved_line_to(node_pos, right_pos, fig)
        if host_node.layout.upper_v_track < (host_node.layout.x -
                                             node_pos.x) / offset:
            host_node.layout.upper_v_track += (host_node.layout.x -
                                               node_pos.x) / offset + offset
    else:
        stop_row = host_node.right_node.layout.row
        _connect_child_to_parent(node,
                                 right_node,
                                 host_lookup,
                                 recon_obj,
                                 fig,
                                 stop_row=stop_row)