Exemplo n.º 1
0
def _fix_transfer(node: tree.Node,
                  left_node,
                  right_node: tree.Node,
                  host_node: tree.Node,
                  host_lookup: dict,
                  parasite_lookup: dict,
                  recon_obj: recon.Reconciliation,
                  node_col: float = None,
                  offset_number: int = 1):
    """
    Checks to see in tranfer node is inconsistent and the tries to fix node if it can be slid down the host edge
    The tries to push a given node forward if possible to correct the assumed inconsistency
    :param node: Node object representing the parasite event being rendered
    :param node: Right node of the node object
    :param left_node: Left node of the node object
    :param right_node: Right node of the node object
    :param host_node: Node object represeting a host that the parasite node is mapped to
    :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 node_col: Column of the node, used when function is called recursively to check the next available transfer spot
    :param offset_number: Used to push node to an available transfer spot
    """
    min_col = host_lookup[recon_obj.mapping_of(
        right_node.name).host].parent_node.layout.col
    max_col = host_node.layout.col
    node_col = node.layout.col
    max_col = min(host_node.layout.col, left_node.layout.col)
    if not (node_col):
        node_col = node.layout.col

    # Checks to see if transfer is inconsistent and if the inconsistency can be fixed by sliding the transfer node down the host edge
    if min_col >= node_col and min_col < max_col and not (_is_sharing_track(
            node, host_node.name, recon_obj)):
        node.set_layout(col=min_col + 0.5, x=min_col + 0.5)
    if min_col < max_col:
        new_value = min_col + render_settings.PUSHED_NODE_OFFSET * offset_number
        if _is_col_taken(new_value, host_lookup, parasite_lookup):
            _fix_transfer(node,
                          left_node,
                          right_node,
                          host_node,
                          host_lookup,
                          parasite_lookup,
                          recon_obj,
                          node_col=new_value,
                          offset_number=offset_number + 1)
        else:
            node.set_layout(col=new_value, x=new_value)
Exemplo n.º 2
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)
Exemplo n.º 3
0
def set_internal_host_nodes(node: tree.Node):
    """ Helper function for set_host_node_layout. """
    if node.is_leaf():
        return
    set_internal_host_nodes(node.left_node)
    set_internal_host_nodes(node.right_node)
    node.layout.row = (node.left_node.layout.row +
                       node.right_node.layout.row) / 2
    node.layout.x = node.layout.col  # This can be scaled if desired
    node.layout.y = node.layout.row  # This can be scaled if desired
Exemplo n.º 4
0
def _set_internal_host_nodes(node: tree.Node):
    """
    Helper function for set_host_node_layout
    :param node: Host Node object that will be rendered
    """
    if node.is_leaf():
        return
    _set_internal_host_nodes(node.left_node)
    _set_internal_host_nodes(node.right_node)
    node.layout.row = (node.left_node.layout.row +
                       node.right_node.layout.row) / 2
    node.layout.x = node.layout.col  # This can be scaled if desired
    node.layout.y = node.layout.row  # This can be scaled if desired
Exemplo n.º 5
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)
Exemplo n.º 6
0
def _populate_host_tracks(node: tree.Node, recon_obj: recon.Reconciliation,
                          host_lookup: dict):
    """
    :param node: Node object
    :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
    """
    mapping_node = recon_obj.mapping_of(node.name)
    event = recon_obj.event_of(mapping_node)
    host_name = mapping_node.host
    host_node = host_lookup[host_name]

    if not (event.event_type is recon.EventType.DUPLICATION
            or event.event_type is recon.EventType.TRANSFER):
        host_node.update_count()
    else:
        if not (_is_sharing_track(node, host_name, recon_obj)):
            host_node.update_count()

    if not (node.is_leaf()):
        _populate_host_tracks(node.left_node, recon_obj, host_lookup)
        _populate_host_tracks(node.right_node, recon_obj, host_lookup)
Exemplo n.º 7
0
def _render_parasite_helper(fig: plot_tools.FigureWrapper, node: tree.Node,
                            recon_obj: recon.Reconciliation, host_lookup: dict,
                            parasite_lookup: dict, show_internal_labels: bool,
                            show_freq: bool, font_size: float,
                            longest_host_name: int):
    """
    Helper function for rendering the parasite tree.
    :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
    :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 font_size: Font size for the text of the tips and internal nodes of the tree
    :param longest_host_name: The number of symbols in the longest host tree tip name
    """
    # mapping_node is of type MappingNode which associates
    # a parasite to a host in a reconciliation
    mapping_node = recon_obj.mapping_of(node.name)

    # A reconciliation has an event_of method which is an object of
    # type Event.
    event = recon_obj.event_of(mapping_node)

    host_name = mapping_node.host

    # host_lookup is a dictionary computed in the Tree class
    # that associates a host name (a string) with the correspond node
    # object for that host.  The node object contains layout information
    # which we need here.
    host_node = host_lookup[host_name]

    # Set parasite node layout
    host_row = host_node.layout.row
    # host_col = host_node.layout.col
    # host_x = host_node.layout.x
    host_y = host_node.layout.y
    node.set_layout(row=host_row, x=node.layout.col, y=host_y)

    # Render parasite node and recurse if not a leaf
    if node.is_leaf():
        node.layout.y += host_node.get_and_update_track(
            tree.Track.HORIZONTAL) * host_node.layout.offset
        _render_parasite_node(fig, node, event, font_size, longest_host_name)
        return

    # If the Node is in their own track, change their position
    if not (_is_sharing_track(node, host_name, recon_obj)):
        node.layout.y += host_node.layout.h_track * host_node.layout.offset

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

    _render_parasite_helper(fig, left_node, recon_obj, host_lookup,
                            parasite_lookup, show_internal_labels, show_freq,
                            font_size, longest_host_name)
    _render_parasite_helper(fig, right_node, recon_obj, host_lookup,
                            parasite_lookup, show_internal_labels, show_freq,
                            font_size, longest_host_name)

    # Checking to see if left node is mapped to the same host node as parent
    if node.layout.row == left_node.layout.row:
        node.set_layout(y=left_node.layout.y)
    elif node.layout.row == right_node.layout.row:
        node.set_layout(y=right_node.layout.y)
    elif event.event_type is recon.EventType.TRANSFER:
        node.layout.y = host_node.layout.y + host_node.layout.h_track * host_node.layout.offset

    #Checks to see if transfer node is inconsistent and if it can be fixed
    if event.event_type is recon.EventType.TRANSFER:
        min_col = host_lookup[recon_obj.mapping_of(
            right_node.name).host].parent_node.layout.col
        if min_col >= node.layout.col:
            _fix_transfer(node, left_node, right_node, host_node, host_lookup,
                          parasite_lookup, recon_obj)

    _render_parasite_branches(fig, node, recon_obj, host_lookup,
                              parasite_lookup)
    _render_parasite_node(fig, node, event, font_size, longest_host_name,
                          show_internal_labels, show_freq)