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)
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
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
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)
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)
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)