def layout(node): #print(node) if node.is_leaf(): if node.name in x_file_names: #make reconstructed bubble size = x[x_file_names.index(node.name)] F = CircleFace(radius=500*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") if taxonomic_names_on_leaves: nameFace = AttrFace("name", fsize=25, fgcolor='black',text_suffix="_"+taxonomy[x_file_names.index(node.name)]) faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: nameFace = AttrFace("name", fsize=25, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in x_file_names: idx = hyp_node_names[node.name][2] size = x[x_file_names.index(node_base_name)+(idx+1)*len(x_file_names)] F = CircleFace(radius=500*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") #print node #print size else: size=0 else: size=0
def layout(node): node_style = NodeStyle() node_style["hz_line_width"] = 10 node_style["vt_line_width"] = 10 node.set_style(node_style) #print(node) if node.is_leaf(): if node.name in org_names: #make reconstructed bubble size = x[org_names.index(node.name)] F = CircleFace(radius=size_factor*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") #Denote that this was a training organism nameFace = AttrFace("name", fsize=font_size, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in org_names: idx = hyp_node_names[node.name][2] size = x[org_names.index(node_base_name)+(idx+1)*len(org_names)] F = CircleFace(radius=size_factor*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") #This is if I want the names of the hypothetical nodes to be printed as well #nameFace = AttrFace("name", fsize=font_size, fgcolor='black') #faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: size=0 else: size=0
def layout(node): #print(node) if node.is_leaf(): if node.name in x_file_names: #make reconstructed bubble size = x[x_file_names.index(node.name)] F = CircleFace(radius=500 * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") if taxonomic_names_on_leaves: nameFace = AttrFace( "name", fsize=25, fgcolor='black', text_suffix="_" + taxonomy[x_file_names.index(node.name)]) faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: nameFace = AttrFace("name", fsize=25, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in x_file_names: idx = hyp_node_names[node.name][2] size = x[x_file_names.index(node_base_name) + (idx + 1) * len(x_file_names)] F = CircleFace(radius=500 * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") #print node #print size else: size = 0 else: size = 0
def makeSupportSymbols(node, secondary_support): #function to make circle with size scaled to base support value and color of circle scaled to the level of the second support value opacity = 0.01 # Let's make the sphere transparent if secondary_support == None: circle_color = "Grey" opacity = 1.0 factor = 6 elif secondary_support >=95.0: circle_color = "Black" opacity = 1.0 factor = 10 elif secondary_support >=70.0: circle_color = "Black" opacity = 1.0 factor = 8 elif secondary_support <70.0: circle_color = "Black" opacity = 1.0 factor = 6 else: print "secondary value unexpected: {}".format(secondary_support()) circle_color = "Red" opacity = 1.0 #circle_color = "#33343E" #a black from the pomacanthus drawing #print "color is {}, bootstrap is {}, opacity is {}".format(color, secondary_support, opacity) support_face = CircleFace(radius=node.support * factor, color=circle_color, style="circle") support_face.opacity = opacity faces.add_face_to_node(support_face, node, 0, position="float-behind")
def layout(node): if node.is_leaf(): ####################################################### #~ Taxon Label Size and Margin Adjustment N = AttrFace("name", fsize=1200, fgcolor="#000000") N.margin_top = 250 N.margin_right = 100 #outside N.margin_left = 1000 #inside N.margin_bottom = 250 ####################################################### ####################################################### #~ Taxon Label Background Color Setting tmp = "<myTaxaonLabel>" #~ if not(node.name.find(tmp)) : N.background.color="#FF9999" ####################################################### faces.add_face_to_node(N, node, 0, position="aligned") if (not node.is_leaf()): S = faces.AttrFace("support", fsize=200, fgcolor="#000000") S.margin_top = 20 S.margin_right = 10 S.margin_left = 20 S.margin_bottom = 20 faces.add_face_to_node(S, node, column=0, position="float") if "support" in node.features: # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=node.support * 20, color="RoyalBlue", style="sphere") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, position="float", column=1) style = NodeStyle() style["size"] = 0 style["vt_line_width"] = 150 style["hz_line_width"] = 150 style["vt_line_type"] = 0 # 0 solid, 1 dashed, 2 dotted style["hz_line_type"] = 0 node.set_style(style) bgcol1 = "#FFCCCC" bgcol2 = "#FFE5CC" bgcol3 = "#FFFFCC" bgcol4 = "#E5FFCC" bgcol5 = "#CCFFCC" bgcol6 = "#CCFFE5" bgcol7 = "#FFCCE5" bgcol8 = "#CCFFFF" bgcol9 = "#CCE5FF" bgcol10 = "#CCCCFF" bgcol11 = "#E5CCFF"
def layout(node): node_style = NodeStyle() node_style["hz_line_width"] = 10 node_style["vt_line_width"] = 10 node.set_style(node_style) #print(node) if node.is_leaf(): if node.name in org_names: #make reconstructed bubble size = x[org_names.index(node.name)] F = CircleFace(radius=size_factor * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") #Denote that this was a training organism nameFace = AttrFace("name", fsize=font_size, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in org_names: idx = hyp_node_names[node.name][2] size = x[org_names.index(node_base_name) + (idx + 1) * len(org_names)] F = CircleFace(radius=size_factor * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") #This is if I want the names of the hypothetical nodes to be printed as well #nameFace = AttrFace("name", fsize=font_size, fgcolor='black') #faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: size = 0 else: size = 0
def layout(node): if node.name in ckm_name_to_perc: ckm_perc = float(ckm_name_to_perc[node.name]) else: ckm_perc = 0 F = CircleFace(radius=3.14*math.sqrt(ckm_perc), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") if label_internal_nodes: faces.add_face_to_node(TextFace(node.name, fsize=7),node, 0, position="branch-top")
def layout(node): if node.is_leaf(): ####################################################### #~ Taxon Label Size and Margin Adjustment N = AttrFace("name", fsize=1200,fgcolor="#000000") N.margin_top = 250 N.margin_right = 100 #outside N.margin_left = 1000 #inside N.margin_bottom = 250 ####################################################### ####################################################### #~ Taxon Label Background Color Setting tmp = "<myTaxaonLabel>" #~ if not(node.name.find(tmp)) : N.background.color="#FF9999" ####################################################### faces.add_face_to_node(N, node, 0, position="aligned") if (not node.is_leaf()) : S=faces.AttrFace("support", fsize=200, fgcolor="#000000") S.margin_top = 20 S.margin_right = 10 S.margin_left = 20 S.margin_bottom = 20 faces.add_face_to_node( S, node, column=0 , position = "float") if "support" in node.features: # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=node.support*20, color="RoyalBlue", style="sphere") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, position="float",column=1) style = NodeStyle() style["size"] = 0 style["vt_line_width"] = 150 style["hz_line_width"] = 150 style["vt_line_type"] = 0 # 0 solid, 1 dashed, 2 dotted style["hz_line_type"] = 0 node.set_style(style) bgcol1="#FFCCCC" bgcol2="#FFE5CC" bgcol3="#FFFFCC" bgcol4="#E5FFCC" bgcol5="#CCFFCC" bgcol6="#CCFFE5" bgcol7="#FFCCE5" bgcol8="#CCFFFF" bgcol9="#CCE5FF" bgcol10="#CCCCFF" bgcol11="#E5CCFF"
def layout(node): if node.is_leaf(): # Add node name to laef nodes N = AttrFace("name", fsize=14, fgcolor="black") faces.add_face_to_node(N, node, 0) if "weight" in node.features: # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=node.weight, color="RoyalBlue", style="sphere") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, 0, position="float")
def layout(node): if not node.is_root(): # give node name to all but the root faces.add_face_to_node(TextFace(node.name), node, 0) # and increase them with the wight if "weight" in node.features: # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=node.weight, color="RoyalBlue", style="sphere") # Let's make the sphere transparent C.opacity = 0.34 # And place as a float face over the tree faces.add_face_to_node(C, node, 0, position="float")
def layout(node): def color(node): if type(node.item) is Value: return "Red" elif type(node.item) is Parameter: return "Yellow" elif node.item.leaf: return "Green" else: return "RoyalBlue" N = AttrFace("name", fsize=14, fgcolor="black") faces.add_face_to_node(N, node, 0) C = CircleFace(radius=node.weight, color=color(node), style="sphere") C.opacity = 0.3 faces.add_face_to_node(C, node, 0, position="float")
def layout(node): if not node.is_root(): # Add node name to laef nodes #N = AttrFace("name", fsize=14, fgcolor="black") #faces.add_face_to_node(N, node, 0) #pass faces.add_face_to_node(TextFace(node.name), node, 0) if "weight" in node.features: # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=node.weight, color="RoyalBlue", style="sphere") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, 0, position="float")
def __layout__(self, node): if node.is_leaf(): # Add node name to laef nodes N = AttrFace("name", fsize=14, fgcolor="black") faces.add_face_to_node(N, node, 0) nstyle = NodeStyle() nstyle["size"] = 0 node.set_style(nstyle) if "internalCount" in node.features: print node.name # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=int(node.internalCount)/10, color="RoyalBlue", style="sphere") T = TextFace("10") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, 0, position="float") faces.add_face_to_node(T, node, 1)
def __layout__(self, node): if node.is_leaf(): # Add node name to laef nodes N = AttrFace("name", fsize=14, fgcolor="black") faces.add_face_to_node(N, node, 0) nstyle = NodeStyle() nstyle["size"] = 0 node.set_style(nstyle) if "internalCount" in node.features: print node.name # Creates a sphere face whose size is proportional to node's # feature "weight" C = CircleFace(radius=int(node.internalCount) / 10, color="RoyalBlue", style="sphere") T = TextFace("10") # Let's make the sphere transparent C.opacity = 0.3 # And place as a float face over the tree faces.add_face_to_node(C, node, 0, position="float") faces.add_face_to_node(T, node, 1)
def MakePlot(x, org_names, ckm30, ckm50, outgroup, outfile, outfilexml, sum_x): #Make sure names are unique names = org_names for name in names: if names.count(name)>1: temp_name = name i=1 for dummy in range(0,names.count(name)-1): #Don't change the last one, just to make sure we don't conflict with the outgroup names[names.index(temp_name)] = temp_name + "_" + str(i) i = i +1 #Normalize the x vector x = map(lambda y: y/sum(x),x) ckm30_norm = np.multiply(ckm30,1/np.diag(ckm30)) ckm50_norm = np.multiply(ckm50,1/np.diag(ckm50)) num_rows = ckm30_norm.shape[0] num_cols = ckm30_norm.shape[1] matrix=list() for i in range(num_rows): matrix.append([.5*(1-.5*ckm30_norm[i,j]-.5*ckm30_norm[j,i])+.5*(1-.5*ckm50_norm[i,j]-.5*ckm50_norm[j,i]) for j in range(i+1)]) #Make the list of distances (ave of the two ckm matrices) ckm_ave_train = .5*ckm30_norm+.5*ckm50_norm ckm_ave_train_dist = dict() for i in range(len(org_names)): ckm_ave_train_dist[org_names[i]] = [.5*ckm_ave_train[i,j]+.5*ckm_ave_train[j,i] for j in range(len(org_names))] #Construct the tree. Note I could use RapidNJ here, but a few tests have shown that the trees that RapidNJ creates are rubbish. dm = _DistanceMatrix(names, matrix) constructor = DistanceTreeConstructor() tree = constructor.nj(dm) t=Tree(tree.format('newick'),format=1) #tree.format('newick') #Phylo.draw_ascii(tree) #Now I will put internal nodes in a certain phylogenetic distance between the root and a given node. #Function to insert a node at a given distance def insert_node(t, name_to_insert, insert_above, dist_along): insert_at_node = t.search_nodes(name=insert_above)[0] parent = (t&insert_above).up orig_branch_length = t.get_distance(insert_at_node,parent) if orig_branch_length < dist_along: raise ValueError("error: dist_along larger than orig_branch_length in PlotPackage.py") removed_node = insert_at_node.detach() removed_node.dist = orig_branch_length - dist_along added_node = parent.add_child(name=name_to_insert, dist=dist_along) added_node.add_child(removed_node) #Function to insert a node some % along a branch, taking into account the ckm distances and nodes already created in the NJ tree (and what distance their descendants are from everyone else) def insert_hyp_node(t, leaf_name, percent, ckm_ave_train_dist, org_names): dists = map(lambda y: abs(y-percent), ckm_ave_train_dist[leaf_name]) nearby_indicies = list() #Add all the organisms that are within 0.05 of the given percent # for i in range(len(dists)): # if dists[i]<=.05: # nearby_indicies.append(i) nearby_names = list() #If there are no nearby indicies, add the closest organism to the given percent if nearby_indicies==[]: nearby_names.append(org_names[dists.index(min(dists))]) else: for i in range(len(nearby_indicies)): nearby_names.append(org_names[i]) mean_dist = np.mean(map(lambda y: ckm_ave_train_dist[leaf_name][org_names.index(y)],nearby_names)) nearby_names.append(leaf_name) LCA = t.get_common_ancestor(nearby_names) LCA_to_leaf_dist = t.get_distance(LCA,leaf_name) #divide the dist to the right/left of the LCA node by the number of percentage points in there if LCA.name==t.name: percent_dist = percent*LCA_to_leaf_dist if mean_dist <= percent: child_node = (t&leaf_name) else: child_node = (t&nearby_names[0])#This means "go up from root" in the direction of the nearest guy ancestor_node = (t&child_node.name).up elif mean_dist <= percent: percent_dist = t.get_distance(LCA) + abs(percent-mean_dist)*(LCA_to_leaf_dist)/(1-mean_dist) child_node = (t&leaf_name) ancestor_node = (t&child_node.name).up else: percent_dist = t.get_distance(LCA) - abs(percent-mean_dist)*(t.get_distance(LCA))/(mean_dist) child_node = (t&leaf_name) ancestor_node = (t&child_node.name).up while t.get_distance(t.name, ancestor_node) > percent_dist: child_node = ancestor_node ancestor_node = (t&child_node.name).up insert_node(t, leaf_name+"_"+str(percent), child_node.name, percent_dist-t.get_distance(t.name, ancestor_node)) #Set outgroup if outgroup in names: t.set_outgroup(t&outgroup) #I will need to check that this outgroup is actually one of the names... else: print("WARNING: the chosen outgroup " + outgroup + " is not in the given taxonomy: ") print(names) print("Proceeding without setting an outgroup. This may cause results to be uninterpretable.") #Insert hypothetical nodes hyp_node_names = dict() cutoffs = [.9,.8,.7,.6,.5,.4,.3,.2,.1] cutoffs = [-.5141*(val**3)+1.0932*(val**2)+0.3824*val for val in cutoffs] for i in range(len(org_names)): xi = x[i:len(x):len(org_names)] for j in range(1,len(cutoffs)+1): if xi[j]>0: insert_hyp_node(t, org_names[i], cutoffs[j-1],ckm_ave_train_dist, org_names) hyp_node_names[org_names[i]+"_"+str(cutoffs[j-1])] = [org_names[i], cutoffs[j-1], j-1] #in case there are "_" in the file names size_factor=250 font_size=55 #Now put the bubbles on the nodes def layout(node): node_style = NodeStyle() node_style["hz_line_width"] = 10 node_style["vt_line_width"] = 10 node.set_style(node_style) #print(node) if node.is_leaf(): if node.name in org_names: #make reconstructed bubble size = x[org_names.index(node.name)] F = CircleFace(radius=size_factor*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") #Denote that this was a training organism nameFace = AttrFace("name", fsize=font_size, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in org_names: idx = hyp_node_names[node.name][2] size = x[org_names.index(node_base_name)+(idx+1)*len(org_names)] F = CircleFace(radius=size_factor*math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F,node, 0, position="branch-right") #This is if I want the names of the hypothetical nodes to be printed as well #nameFace = AttrFace("name", fsize=font_size, fgcolor='black') #faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: size=0 else: size=0 ts = TreeStyle() ts.layout_fn = layout ts.mode = "r" #ts.mode = "c" ts.scale = 2*1000 ts.show_leaf_name = False ts.min_leaf_separation = 50 F = CircleFace(radius=.87*size_factor, color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 ts.legend.add_face(F,0) ts.legend.add_face(TextFace(" Inferred relative abundance",fsize=1.5*font_size,fgcolor="Blue"),1) ts.legend.add_face(TextFace(" Total absolute abundance depicted " + str(sum_x)[0:8], fsize=1.5*font_size,fgcolor="Black"),1) ts.legend_position=4 #t.show(tree_style=ts) t.render(outfile, w=550, units="mm", tree_style=ts) #Redner the XML file project = Phyloxml() phylo = phyloxml.PhyloxmlTree(newick=t.write(format=0, features=[])) project.add_phylogeny(phylo) project.export(open(outfilexml,'w'))
def style_node2(node, colour, size): C = CircleFace(radius = size, color = colour, style="sphere") C.opacity = 0.8 node.add_face(C, 0, position="float")
def MakePlot(x, org_names, ckm30, ckm50, outgroup, outfile, outfilexml, sum_x): #Make sure names are unique names = org_names for name in names: if names.count(name) > 1: temp_name = name i = 1 for dummy in range( 0, names.count(name) - 1 ): #Don't change the last one, just to make sure we don't conflict with the outgroup names[names.index(temp_name)] = temp_name + "_" + str(i) i = i + 1 #Normalize the x vector x = map(lambda y: y / sum(x), x) ckm30_norm = np.multiply(ckm30, 1 / np.diag(ckm30)) ckm50_norm = np.multiply(ckm50, 1 / np.diag(ckm50)) num_rows = ckm30_norm.shape[0] num_cols = ckm30_norm.shape[1] matrix = list() for i in range(num_rows): matrix.append([ .5 * (1 - .5 * ckm30_norm[i, j] - .5 * ckm30_norm[j, i]) + .5 * (1 - .5 * ckm50_norm[i, j] - .5 * ckm50_norm[j, i]) for j in range(i + 1) ]) #Make the list of distances (ave of the two ckm matrices) ckm_ave_train = .5 * ckm30_norm + .5 * ckm50_norm ckm_ave_train_dist = dict() for i in range(len(org_names)): ckm_ave_train_dist[org_names[i]] = [ .5 * ckm_ave_train[i, j] + .5 * ckm_ave_train[j, i] for j in range(len(org_names)) ] #Construct the tree. Note I could use RapidNJ here, but a few tests have shown that the trees that RapidNJ creates are rubbish. dm = _DistanceMatrix(names, matrix) constructor = DistanceTreeConstructor() tree = constructor.nj(dm) t = Tree(tree.format('newick'), format=1) #tree.format('newick') #Phylo.draw_ascii(tree) #Now I will put internal nodes in a certain phylogenetic distance between the root and a given node. #Function to insert a node at a given distance def insert_node(t, name_to_insert, insert_above, dist_along): insert_at_node = t.search_nodes(name=insert_above)[0] parent = (t & insert_above).up orig_branch_length = t.get_distance(insert_at_node, parent) if orig_branch_length < dist_along: raise ValueError( "error: dist_along larger than orig_branch_length in PlotPackage.py" ) removed_node = insert_at_node.detach() removed_node.dist = orig_branch_length - dist_along added_node = parent.add_child(name=name_to_insert, dist=dist_along) added_node.add_child(removed_node) #Function to insert a node some % along a branch, taking into account the ckm distances and nodes already created in the NJ tree (and what distance their descendants are from everyone else) def insert_hyp_node(t, leaf_name, percent, ckm_ave_train_dist, org_names): dists = map(lambda y: abs(y - percent), ckm_ave_train_dist[leaf_name]) nearby_indicies = list() #Add all the organisms that are within 0.05 of the given percent # for i in range(len(dists)): # if dists[i]<=.05: # nearby_indicies.append(i) nearby_names = list() #If there are no nearby indicies, add the closest organism to the given percent if nearby_indicies == []: nearby_names.append(org_names[dists.index(min(dists))]) else: for i in range(len(nearby_indicies)): nearby_names.append(org_names[i]) mean_dist = np.mean( map(lambda y: ckm_ave_train_dist[leaf_name][org_names.index(y)], nearby_names)) nearby_names.append(leaf_name) LCA = t.get_common_ancestor(nearby_names) LCA_to_leaf_dist = t.get_distance(LCA, leaf_name) #divide the dist to the right/left of the LCA node by the number of percentage points in there if LCA.name == t.name: percent_dist = percent * LCA_to_leaf_dist if mean_dist <= percent: child_node = (t & leaf_name) else: child_node = ( t & nearby_names[0] ) #This means "go up from root" in the direction of the nearest guy ancestor_node = (t & child_node.name).up elif mean_dist <= percent: percent_dist = t.get_distance(LCA) + abs(percent - mean_dist) * ( LCA_to_leaf_dist) / (1 - mean_dist) child_node = (t & leaf_name) ancestor_node = (t & child_node.name).up else: percent_dist = t.get_distance(LCA) - abs(percent - mean_dist) * ( t.get_distance(LCA)) / (mean_dist) child_node = (t & leaf_name) ancestor_node = (t & child_node.name).up while t.get_distance(t.name, ancestor_node) > percent_dist: child_node = ancestor_node ancestor_node = (t & child_node.name).up insert_node(t, leaf_name + "_" + str(percent), child_node.name, percent_dist - t.get_distance(t.name, ancestor_node)) #Set outgroup if outgroup in names: t.set_outgroup( t & outgroup ) #I will need to check that this outgroup is actually one of the names... else: print("WARNING: the chosen outgroup " + outgroup + " is not in the given taxonomy: ") print(names) print( "Proceeding without setting an outgroup. This may cause results to be uninterpretable." ) #Insert hypothetical nodes hyp_node_names = dict() cutoffs = [.9, .8, .7, .6, .5, .4, .3, .2, .1] cutoffs = [ -.5141 * (val**3) + 1.0932 * (val**2) + 0.3824 * val for val in cutoffs ] for i in range(len(org_names)): xi = x[i:len(x):len(org_names)] for j in range(1, len(cutoffs) + 1): if xi[j] > 0: insert_hyp_node(t, org_names[i], cutoffs[j - 1], ckm_ave_train_dist, org_names) hyp_node_names[org_names[i] + "_" + str(cutoffs[j - 1])] = [ org_names[i], cutoffs[j - 1], j - 1 ] #in case there are "_" in the file names size_factor = 250 font_size = 55 #Now put the bubbles on the nodes def layout(node): node_style = NodeStyle() node_style["hz_line_width"] = 10 node_style["vt_line_width"] = 10 node.set_style(node_style) #print(node) if node.is_leaf(): if node.name in org_names: #make reconstructed bubble size = x[org_names.index(node.name)] F = CircleFace(radius=size_factor * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") #Denote that this was a training organism nameFace = AttrFace("name", fsize=font_size, fgcolor='black') faces.add_face_to_node(nameFace, node, 0, position="branch-right") elif node.name in hyp_node_names: #Otherwise it's a hypothetical node, just use recon x node_base_name = hyp_node_names[node.name][0] percent = hyp_node_names[node.name][1] if node_base_name in org_names: idx = hyp_node_names[node.name][2] size = x[org_names.index(node_base_name) + (idx + 1) * len(org_names)] F = CircleFace(radius=size_factor * math.sqrt(size), color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 faces.add_face_to_node(F, node, 0, position="branch-right") #This is if I want the names of the hypothetical nodes to be printed as well #nameFace = AttrFace("name", fsize=font_size, fgcolor='black') #faces.add_face_to_node(nameFace, node, 0, position="branch-right") else: size = 0 else: size = 0 ts = TreeStyle() ts.layout_fn = layout ts.mode = "r" #ts.mode = "c" ts.scale = 2 * 1000 ts.show_leaf_name = False ts.min_leaf_separation = 50 F = CircleFace(radius=.87 * size_factor, color="RoyalBlue", style="sphere") F.border.width = None F.opacity = 0.6 ts.legend.add_face(F, 0) ts.legend.add_face( TextFace(" Inferred relative abundance", fsize=1.5 * font_size, fgcolor="Blue"), 1) ts.legend.add_face( TextFace(" Total absolute abundance depicted " + str(sum_x)[0:8], fsize=1.5 * font_size, fgcolor="Black"), 1) ts.legend_position = 4 #t.show(tree_style=ts) t.render(outfile, w=550, units="mm", tree_style=ts) #Redner the XML file project = Phyloxml() phylo = phyloxml.PhyloxmlTree(newick=t.write(format=0, features=[])) project.add_phylogeny(phylo) project.export(open(outfilexml, 'w'))