def render(root_node, img, hide_root=False): '''main render function. hide_root option is used when render trees as Faces ''' mode = img.mode orientation = img.orientation arc_span = img.arc_span layout_fn = img._layout_handler parent = _TreeItem() n2i = parent.n2i # node to items n2f = parent.n2f # node to faces parent.bg_layer = _EmptyItem(parent) parent.tree_layer = _EmptyItem(parent) parent.float_layer = _EmptyItem(parent) parent.float_behind_layer = _EmptyItem(parent) TREE_LAYERS = [parent.bg_layer, parent.tree_layer, parent.float_layer, parent.float_behind_layer] parent.bg_layer.setZValue(0) parent.tree_layer.setZValue(2) parent.float_behind_layer.setZValue(1) parent.float_layer.setZValue(3) # This could be used to handle aligned faces in internal # nodes. virtual_leaves = 0 if img.show_branch_length: bl_face = faces.AttrFace("dist", fsize=8, ftype="Arial", fgcolor="black", formatter = "%0.3g") if img.show_branch_support: su_face = faces.AttrFace("support", fsize=8, ftype="Arial", fgcolor="darkred", formatter = "%0.3g") if img.show_leaf_name: na_face = faces.AttrFace("name", fsize=10, ftype="Arial", fgcolor="black") for n in root_node.traverse(is_leaf_fn=_leaf): set_style(n, layout_fn) if img.show_branch_length: faces.add_face_to_node(bl_face, n, 0, position="branch-top") if not _leaf(n) and img.show_branch_support: faces.add_face_to_node(su_face, n, 0, position="branch-bottom") if _leaf(n) and n.name and img.show_leaf_name: faces.add_face_to_node(na_face, n, 0, position="branch-right") if _leaf(n):# or len(n.img_style["_faces"]["aligned"]): virtual_leaves += 1 update_node_faces(n, n2f, img) rot_step = float(arc_span) / virtual_leaves #rot_step = float(arc_span) / len([n for n in root_node.traverse() if _leaf(n)]) # Calculate optimal branch length if img._scale is not None: init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) elif img.scale is None: # create items and calculate node dimensions skipping branch lengths init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) if mode == 'r': if img.optimal_scale_level == "full": scales = [(i.widths[1]/n.dist) for n,i in n2i.iteritems() if n.dist] img._scale = max(scales) if scales else 0.0 else: farthest, dist = root_node.get_farthest_leaf(topology_only=img.force_topology) img._scale = img.tree_width / dist if dist else 0.0 update_branch_lengths(root_node, n2i, n2f, img) else: img._scale = crender.calculate_optimal_scale(root_node, n2i, rot_step, img) #print "OPTIMAL circular scale", img._scale update_branch_lengths(root_node, n2i, n2f, img) init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) else: # create items and calculate node dimensions CONSIDERING branch lengths img._scale = img.scale init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) #print "USING scale", img._scale # Draw node content for node in root_node.traverse(is_leaf_fn=_leaf): if node is not root_node or not hide_root: render_node_content(node, n2i, n2f, img) # Adjust content to rect or circular layout mainRect = parent.rect() if mode == "c": tree_radius = crender.render_circular(root_node, n2i, rot_step) mainRect.adjust(-tree_radius, -tree_radius, tree_radius, tree_radius) else: iwidth = n2i[root_node].fullRegion.width() iheight = n2i[root_node].fullRegion.height() mainRect.adjust(0, 0, iwidth, iheight) tree_radius = iwidth # Add extra layers: aligned faces, floating faces, node # backgrounds, etc. The order by which the following methods are # called IS IMPORTANT render_floatings(n2i, n2f, img, parent.float_layer, parent.float_behind_layer) aligned_region_width = render_aligned_faces(img, mainRect, parent.tree_layer, n2i, n2f) render_backgrounds(img, mainRect, parent.bg_layer, n2i, n2f) # rotate if necessary in circular images. flip and adjust if mirror orientation. adjust_faces_to_tranformations(img, mainRect, n2i, n2f, TREE_LAYERS) # Rotate main image if necessary parent.setRect(mainRect) parent.setPen(QtGui.QPen(QtCore.Qt.NoPen)) if img.rotation: rect = parent.boundingRect() x = rect.x() + (rect.width()/2.0) y = rect.y() + (rect.height()/2.0) parent.setTransform(QtGui.QTransform().translate(x, y).rotate(img.rotation).translate(-x, -y)) # Creates the main tree item that will act as frame for the whole image frame = QtGui.QGraphicsRectItem() parent.setParentItem(frame) mainRect = parent.mapToScene(mainRect).boundingRect() mainRect.adjust(-img.margin_left, -img.margin_top, \ img.margin_right, img.margin_bottom) # Fix negative coordinates, so main item always starts at 0,0 topleft = mainRect.topLeft() _x = abs(topleft.x()) if topleft.x() < 0 else 0 _y = abs(topleft.y()) if topleft.y() < 0 else 0 if _x or _y: parent.moveBy(_x, _y) mainRect.adjust(_x, _y, _x, _y) # Add extra components and adjust mainRect to them add_legend(img, mainRect, frame) add_title(img, mainRect, frame) add_scale(img, mainRect, frame) frame.setRect(mainRect) # Draws a border around the tree if not img.show_border: frame.setPen(QtGui.QPen(QtCore.Qt.NoPen)) else: frame.setPen(QtGui.QPen(QtGui.QColor("black"))) return frame, n2i, n2f
def render(root_node, img, hide_root=False): '''main render function. hide_root option is used when render trees as Faces ''' mode = img.mode orientation = img.orientation arc_span = img.arc_span layout_fn = img._layout_handler parent = _TreeItem() n2i = parent.n2i # node to items n2f = parent.n2f # node to faces parent.bg_layer = _EmptyItem(parent) parent.tree_layer = _EmptyItem(parent) parent.float_layer = _EmptyItem(parent) parent.float_behind_layer = _EmptyItem(parent) TREE_LAYERS = [parent.bg_layer, parent.tree_layer, parent.float_layer, parent.float_behind_layer] parent.bg_layer.setZValue(0) parent.tree_layer.setZValue(2) parent.float_behind_layer.setZValue(1) parent.float_layer.setZValue(3) # This could be used to handle aligned faces in internal # nodes. virtual_leaves = 0 if img.show_branch_length: bl_face = faces.AttrFace("dist", fsize=8, ftype="Arial", fgcolor="black", formatter = "%0.3g") if img.show_branch_support: su_face = faces.AttrFace("support", fsize=8, ftype="Arial", fgcolor="darkred", formatter = "%0.3g") if img.show_leaf_name: na_face = faces.AttrFace("name", fsize=10, ftype="Arial", fgcolor="black") for n in root_node.traverse(is_leaf_fn=_leaf): set_style(n, layout_fn) if img.show_branch_length: faces.add_face_to_node(bl_face, n, 0, position="branch-top") if not _leaf(n) and img.show_branch_support: faces.add_face_to_node(su_face, n, 0, position="branch-bottom") if _leaf(n) and img.show_leaf_name: faces.add_face_to_node(na_face, n, 0, position="branch-right") if _leaf(n):# or len(n.img_style["_faces"]["aligned"]): virtual_leaves += 1 update_node_faces(n, n2f, img) rot_step = float(arc_span) / virtual_leaves #rot_step = float(arc_span) / len([n for n in root_node.traverse() if _leaf(n)]) # Calculate optimal branch length if img._scale is not None: init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) elif img.scale is None: # create items and calculate node dimensions skipping branch lengths init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) if mode == 'r': if img.optimal_scale_level == "full": scales = [(i.widths[1]/n.dist) for n,i in n2i.iteritems() if n.dist] img._scale = max(scales) if scales else 0.0 else: farthest, dist = root_node.get_farthest_leaf(topology_only=img.force_topology) img._scale = img.tree_width / dist if dist else 0.0 update_branch_lengths(root_node, n2i, n2f, img) else: img._scale = crender.calculate_optimal_scale(root_node, n2i, rot_step, img) #print "OPTIMAL circular scale", img._scale update_branch_lengths(root_node, n2i, n2f, img) init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) else: # create items and calculate node dimensions CONSIDERING branch lengths img._scale = img.scale init_items(root_node, parent, n2i, n2f, img, rot_step, hide_root) #print "USING scale", img._scale # Draw node content for node in root_node.traverse(is_leaf_fn=_leaf): if node is not root_node or not hide_root: render_node_content(node, n2i, n2f, img) # Adjust content to rect or circular layout mainRect = parent.rect() if mode == "c": tree_radius = crender.render_circular(root_node, n2i, rot_step) mainRect.adjust(-tree_radius, -tree_radius, tree_radius, tree_radius) else: iwidth = n2i[root_node].fullRegion.width() iheight = n2i[root_node].fullRegion.height() mainRect.adjust(0, 0, iwidth, iheight) tree_radius = iwidth # Add extra layers: aligned faces, floating faces, node # backgrounds, etc. The order by which the following methods are # called IS IMPORTANT render_floatings(n2i, n2f, img, parent.float_layer, parent.float_behind_layer) aligned_region_width = render_aligned_faces(img, mainRect, parent.tree_layer, n2i, n2f) render_backgrounds(img, mainRect, parent.bg_layer, n2i, n2f) # rotate if necessary in circular images. flip and adjust if mirror orientation. adjust_faces_to_tranformations(img, mainRect, n2i, n2f, TREE_LAYERS) # Rotate main image if necessary parent.setRect(mainRect) parent.setPen(QtGui.QPen(QtCore.Qt.NoPen)) if img.rotation: rect = parent.boundingRect() x = rect.x() + (rect.width()/2.0) y = rect.y() + (rect.height()/2.0) parent.setTransform(QtGui.QTransform().translate(x, y).rotate(img.rotation).translate(-x, -y)) # Creates the main tree item that will act as frame for the whole image frame = QtGui.QGraphicsRectItem() parent.setParentItem(frame) mainRect = parent.mapToScene(mainRect).boundingRect() mainRect.adjust(-img.margin_left, -img.margin_top, \ img.margin_right, img.margin_bottom) # Fix negative coordinates, so main item always starts at 0,0 topleft = mainRect.topLeft() _x = abs(topleft.x()) if topleft.x() < 0 else 0 _y = abs(topleft.y()) if topleft.y() < 0 else 0 if _x or _y: parent.moveBy(_x, _y) mainRect.adjust(_x, _y, _x, _y) # Add extra components and adjust mainRect to them add_legend(img, mainRect, frame) add_title(img, mainRect, frame) add_scale(img, mainRect, frame) frame.setRect(mainRect) # Draws a border around the tree if not img.show_border: frame.setPen(QtGui.QPen(QtCore.Qt.NoPen)) else: frame.setPen(QtGui.QPen(QtGui.QColor("black"))) return frame, n2i, n2f
def set_node_size(node, n2i, n2f, img): scale = img.scale min_separation = img.min_leaf_separation item = n2i[node] if img.force_topology: branch_length = item.branch_length = float(scale) else: branch_length = item.branch_length = float(node.dist * scale) # Organize faces by groups faceblock = update_node_faces(node, n2f, img) aligned_height = 0 if _leaf(node): if img.mode == "r": aligned_height = faceblock["aligned"].h elif img.mode == "c": # aligned faces in circular mode are adjusted afterwords. The # min radius of the largest aligned faces will be calculated. pass # Total height required by the node. I cannot sum up the height of # all elements, since the position of some of them are forced to # be on top or at the bottom of branches. This fact can produce # and unbalanced nodeRegion center. Here, I only need to know # about the imbalance size to correct node height. The center will # be calculated later according to the parent position. top_half_h = ( (node.img_style["size"]/2) + node.img_style["hz_line_width"]/2 + faceblock["branch-top"].h ) bottom_half_h =( (node.img_style["size"]/2) + node.img_style["hz_line_width"]/2 + faceblock["branch-bottom"].h ) h1 = top_half_h + bottom_half_h h2 = max(faceblock["branch-right"].h, \ aligned_height, \ min_separation ) h = max(h1, h2) imbalance = abs(top_half_h - bottom_half_h) if imbalance > h2/2: h += imbalance - (h2/2) # This adds a vertical margin around the node elements h += img.branch_vertical_margin # Total width required by the node w = sum([max(branch_length + node.img_style["size"], faceblock["branch-top"].w + node.img_style["size"], faceblock["branch-bottom"].w + node.img_style["size"], ), faceblock["branch-right"].w] ) w += node.img_style["vt_line_width"] # rightside faces region item.facesRegion.setRect(0, 0, faceblock["branch-right"].w, h) # Node region item.nodeRegion.setRect(0, 0, w, h) # This is the node total region covered by the node item.fullRegion.setRect(0, 0, w, h)