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