def bub_tree(tree, fasta, outfile1, root, types, c_dict, show, size, colours, field1, field2, scale, multiplier, dna): """ :param tree: tree object from ete :param fasta: the fasta file used to make the tree :param outfile1: outfile suffix :param root: sequence name to use as root :param types: tree type: circular (c) or rectangle (r) :param c_dict: dictionary mapping colour to time point (from col_map) :param show: show the tree in a gui (y/n) :param size: scale the terminal nodes by frequency information (y/n) :param colours: if using a matched fasta file, colour the sequence by charge/IUPAC :param field1: the field that contains the size/frequency value :param field2: the field that contains the size/frequency value :param scale: how much to scale the x axis :param multiplier :param dna true/false, is sequence a DNA sequence? :param t_list list of time points :return: None, outputs svg/pdf image of the tree """ if multiplier is None: mult = 500 else: mult = multiplier if dna: dna_prot = 'dna' bg_c = { 'A': 'green', 'C': 'blue', 'G': 'black', 'T': 'red', '-': 'grey', 'X': 'white' } fg_c = { 'A': 'black', 'C': 'black', 'G': 'black', 'T': 'black', '-': 'black', 'X': 'white' } else: dna_prot = 'aa' bg_c = { 'K': '#145AFF', 'R': '#145AFF', 'H': '#8282D2', 'E': '#E60A0A', 'D': '#E60A0A', 'N': '#00DCDC', 'Q': '#00DCDC', 'S': '#FA9600', 'T': '#FA9600', 'L': '#0F820F', 'I': '#0F820F', 'V': '#0F820F', 'Y': '#3232AA', 'F': '#3232AA', 'W': '#B45AB4', 'C': '#E6E600', 'M': '#E6E600', 'A': '#C8C8C8', 'G': '#EBEBEB', 'P': '#DC9682', '-': 'grey', 'X': 'white' } fg_c = { 'K': 'black', 'R': 'black', 'H': 'black', 'E': 'black', 'D': 'black', 'N': 'black', 'Q': 'black', 'S': 'black', 'T': 'black', 'L': 'black', 'I': 'black', 'V': 'black', 'Y': 'black', 'F': 'black', 'W': 'black', 'C': 'black', 'M': 'black', 'A': 'black', 'G': 'black', 'P': 'black', '-': 'grey', 'X': 'white' } if colours == 3: bg_c = None fg_c = None # outfile3 = str(outfile1.replace(".svg", ".nwk")) tstyle = TreeStyle() tstyle.force_topology = False tstyle.mode = types tstyle.scale = scale tstyle.min_leaf_separation = 0 tstyle.optimal_scale_level = 'full' # 'mid' # tstyle.complete_branch_lines_when_necessary = False if types == 'c': tstyle.root_opening_factor = 0.25 tstyle.draw_guiding_lines = False tstyle.guiding_lines_color = 'slateblue' tstyle.show_leaf_name = False tstyle.allow_face_overlap = True tstyle.show_branch_length = False tstyle.show_branch_support = False TreeNode(format=0, support=True) # tnode = TreeNode() if root is not None: tree.set_outgroup(root) # else: # r = tnode.get_midpoint_outgroup() # print("r", r) # tree.set_outgroup(r) time_col = [] for node in tree.traverse(): # node.ladderize() if node.is_leaf() is True: try: name = node.name.split("_") time = name[field2] kind = name[3] # print(name) except: time = 'zero' name = node.name print("Incorrect name format for ", node.name) if size is True: try: s = 20 + float(name[field1]) * mult except: s = 20 print("No frequency information for ", node.name) else: s = 20 colour = c_dict[time] time_col.append((time, colour)) nstyle = NodeStyle() nstyle["fgcolor"] = colour nstyle["size"] = s nstyle["hz_line_width"] = 10 nstyle["vt_line_width"] = 10 nstyle["hz_line_color"] = colour nstyle["vt_line_color"] = 'black' nstyle["hz_line_type"] = 0 nstyle["vt_line_type"] = 0 node.set_style(nstyle) if root is not None and node.name == root: # place holder in case you want to do something with the root leaf print('root is ', node.name) # nstyle["shape"] = "square" # nstyle["fgcolor"] = "black" # nstyle["size"] = s # nstyle["shape"] = "circle" # node.set_style(nstyle) else: nstyle["shape"] = "circle" node.set_style(nstyle) if fasta is not None: seq = fasta[str(node.name)] seqFace = SequenceFace(seq, seqtype=dna_prot, fsize=10, fg_colors=fg_c, bg_colors=bg_c, codon=None, col_w=40, alt_col_w=3, special_col=None, interactive=True) # seqFace = SeqMotifFace(seq=seq, motifs=None, seqtype=dna_prot, gap_format=' ', seq_format='()', scale_factor=20, # height=20, width=50, fgcolor='white', bgcolor='grey', gapcolor='white', ) # seqFace = SeqMotifFace(seq, seq_format="seq", fgcolor=fg_c, bgcolor=bg_c) #interactive=True (tree & node.name).add_face(seqFace, 0, "aligned") else: nstyle = NodeStyle() nstyle["size"] = 0.1 nstyle["hz_line_width"] = 10 nstyle["vt_line_width"] = 10 node.set_style(nstyle) continue tree.ladderize() # tnode.ladderize() legendkey = sorted(set(time_col)) legendkey = [(tp, col) for tp, col in legendkey] # legendkey.insert(0, ('Root', 'black')) legendkey.append(('', 'white')) for tm, clr in legendkey: tstyle.legend.add_face(faces.CircleFace(30, clr), column=0) tstyle.legend.add_face(faces.TextFace('\t' + tm, ftype='Arial', fsize=60, fgcolor='black', tight_text=True), column=1) if show is True: tree.show(tree_style=tstyle) tree.render(outfile1, dpi=600, tree_style=tstyle)
def layout(self, node): scale=self.scaling eps = .000000001 node_taxid = str(node.taxid) if node_taxid in self.profile_tax_id_to_percentage and self.profile_tax_id_to_percentage[node_taxid]['percentage'] > 0.: if (scale=="log"): size_profile = (np.log(self.profile_tax_id_to_percentage[node_taxid]['percentage'])+9.)/11.*self.label_size elif(scale=="sqrt"): size_profile = (np.sqrt(self.profile_tax_id_to_percentage[node_taxid]['percentage'])-0.0000316227766)/10*self.label_size elif(scale=="exponent"): size_profile = (np.exp(self.profile_tax_id_to_percentage[node_taxid]['percentage'])-1.000000001)/np.exp(100)*self.label_size elif(scale=="linear"): size_profile = (self.profile_tax_id_to_percentage[node_taxid]['percentage'])/100*self.label_size else: size_profile = eps if node_taxid in self.ground_truth_tax_id_to_percentage and self.ground_truth_tax_id_to_percentage[node_taxid]['percentage'] > 0.: if (scale=="log"): size_ground_truth = (np.log(self.ground_truth_tax_id_to_percentage[node_taxid]['percentage'])+9.)/11.*self.label_size elif(scale=="sqrt"): size_ground_truth = (np.sqrt(self.ground_truth_tax_id_to_percentage[node_taxid]['percentage'])-0.0000316227766)/10*self.label_size elif(scale=="exponent"): size_ground_truth = (np.exp(self.ground_truth_tax_id_to_percentage[node_taxid]['percentage'])-1.000000001)/np.exp(100)*self.label_size elif(scale=="linear"): size_ground_truth = (self.ground_truth_tax_id_to_percentage[node_taxid]['percentage'])/100*self.label_size else: size_ground_truth = eps chart_sizes = np.array([size_profile, size_ground_truth]) if not np.sum(chart_sizes) == 0: chart_sizes = 100 * (chart_sizes / np.sum(chart_sizes)) if(self.labels=="All"): F2 = TextFace(abbreaviate_name(node.sci_name), tight_text=True, fsize=self.font_size) # use the scientific name faces.add_face_to_node(F2, node, column=0, position="branch-right") elif(self.labels=="Leaf"): if node.is_leaf(): F2 = TextFace(abbreaviate_name(node.sci_name), tight_text=True, fsize=self.font_size) # use the scientific name faces.add_face_to_node(F2, node, column=0, position="branch-right") if(self.layt=="Pie"): # PIE CHART size = max([size_profile, size_ground_truth]) F = faces.PieChartFace(chart_sizes,colors=['#1b9e77', '#d95f02'],width=size, height=size) elif(self.layt=="Circle"): #TWO CIRCLES SIDE BY SIDE F=faces.CircleFace(radius=size_profile, color="#1b9e77", style='circle', label=None) F1=faces.CircleFace(radius=size_ground_truth, color="#d95f02", style='circle', label=None) F1.border.width = None F1.opacity = 0.6 faces.add_face_to_node(F1, node, 0, position="float-behind") elif(self.layt=="Rectangle"): #TWO CIRCLES SIDE BY SIDE F=faces.RectFace(width=size_profile, height=self.label_width, fgcolor="#1b9e77",bgcolor="#1b9e77", label=None) F1=faces.RectFace(width=size_ground_truth, height=self.label_width, fgcolor="#d95f02",bgcolor="#d95f02", label=None) F1.border.width = None F1.opacity = 0.6 faces.add_face_to_node(F1, node, 0, position="float-behind") faces.add_face_to_node(F, node, 0, position="float-behind") F.border.width = None F.opacity = 0.6
def sphere_map(node): # Creates a random color sphere face that will be floating over nodes bubble = faces.CircleFace(random.randint(5, 40), random_color(), "sphere") bubble.opacity = 0.7 faces.add_face_to_node(bubble, node, 0, position="float")
position="aligned") I.aligned_header.add_face(faces.TextFace("H1"), 0) I.aligned_header.add_face(faces.TextFace("H1"), 1) I.aligned_header.add_face(faces.TextFace("H1"), 2) I.aligned_header.add_face(faces.TextFace("H1111111111111"), 3) I.aligned_header.add_face(faces.TextFace("H1"), 4) I.aligned_foot.add_face(faces.TextFace("FO1"), 0) I.aligned_foot.add_face(faces.TextFace("FO1"), 1) I.aligned_foot.add_face(faces.TextFace("FO1"), 2) I.aligned_foot.add_face(faces.TextFace("F1"), 3) I.aligned_foot.add_face(faces.TextFace("FO1"), 4) I.legend.add_face(faces.CircleFace(30, random_color(), "sphere"), 0) I.legend.add_face(faces.CircleFace(30, random_color(), "sphere"), 0) I.legend.add_face(faces.TextFace("HOLA"), 1) I.legend.add_face(faces.TextFace("HOLA"), 1) # Creates a random tree with 10 leaves t2 = Tree() t2.populate(10) # Creates a fixed NodeStyle object containing a TreeFace (A tree image # as a face within another tree image) # t.add_face(faces.TreeFace(t2, I), "branch-right", 0) # Attach the fixed style to the first child of the root node # t.children[0].img_style = style I.rotation = 90
def run(args): if args.text_mode: from ete3 import Tree for tindex, tfile in enumerate(args.src_tree_iterator): #print tfile if args.raxml: nw = re.sub(":(\d+\.\d+)\[(\d+)\]", ":\\1[&&NHX:support=\\2]", open(tfile).read()) t = Tree(nw) else: t = Tree(tfile) print( t.get_ascii(show_internal=args.show_internal_names, attributes=args.show_attributes)) return import random import re import colorsys from collections import defaultdict from ete3 import (Tree, PhyloTree, TextFace, RectFace, faces, TreeStyle, add_face_to_node, random_color) global FACES if args.face: FACES = parse_faces(args.face) else: FACES = [] # VISUALIZATION ts = TreeStyle() ts.mode = args.mode ts.show_leaf_name = True ts.tree_width = args.tree_width for f in FACES: if f["value"] == "@name": ts.show_leaf_name = False break if args.as_ncbi: ts.show_leaf_name = False FACES.extend( parse_faces([ 'value:@sci_name, size:10, fstyle:italic', 'value:@taxid, color:grey, size:6, format:" - %s"', 'value:@sci_name, color:steelblue, size:7, pos:b-top, nodetype:internal', 'value:@rank, color:indianred, size:6, pos:b-bottom, nodetype:internal', ])) if args.alg: FACES.extend( parse_faces([ 'value:@sequence, size:10, pos:aligned, ftype:%s' % args.alg_type ])) if args.heatmap: FACES.extend( parse_faces(['value:@name, size:10, pos:aligned, ftype:heatmap'])) if args.bubbles: for bubble in args.bubbles: FACES.extend( parse_faces([ 'value:@%s, pos:float, ftype:bubble, opacity:0.4' % bubble, ])) ts.branch_vertical_margin = args.branch_separation if args.show_support: ts.show_branch_support = True if args.show_branch_length: ts.show_branch_length = True if args.force_topology: ts.force_topology = True ts.layout_fn = lambda x: None for tindex, tfile in enumerate(args.src_tree_iterator): #print tfile if args.raxml: nw = re.sub(":(\d+\.\d+)\[(\d+)\]", ":\\1[&&NHX:support=\\2]", open(tfile).read()) t = PhyloTree(nw) else: t = PhyloTree(tfile) if args.alg: t.link_to_alignment(args.alg, alg_format=args.alg_format) if args.heatmap: DEFAULT_COLOR_SATURATION = 0.3 BASE_LIGHTNESS = 0.7 def gradient_color(value, max_value, saturation=0.5, hue=0.1): def rgb2hex(rgb): return '#%02x%02x%02x' % rgb def hls2hex(h, l, s): return rgb2hex( tuple([ int(x * 255) for x in colorsys.hls_to_rgb(h, l, s) ])) lightness = 1 - (value * BASE_LIGHTNESS) / max_value return hls2hex(hue, lightness, DEFAULT_COLOR_SATURATION) heatmap_data = {} max_value, min_value = None, None for line in open(args.heatmap): if line.startswith('#COLNAMES'): pass elif line.startswith('#') or not line.strip(): pass else: fields = line.split('\t') name = fields[0].strip() values = [float(x) if x else None for x in fields[1:]] maxv = max(values) minv = min(values) if max_value is None or maxv > max_value: max_value = maxv if min_value is None or minv < min_value: min_value = minv heatmap_data[name] = values heatmap_center_value = 0 heatmap_color_center = "white" heatmap_color_up = 0.3 heatmap_color_down = 0.7 heatmap_color_missing = "black" heatmap_max_value = abs(heatmap_center_value - max_value) heatmap_min_value = abs(heatmap_center_value - min_value) if heatmap_center_value <= min_value: heatmap_max_value = heatmap_min_value + heatmap_max_value else: heatmap_max_value = max(heatmap_min_value, heatmap_max_value) # scale the tree if not args.height: args.height = None if not args.width: args.width = None f2color = {} f2last_seed = {} for node in t.traverse(): node.img_style['size'] = 0 if len(node.children) == 1: node.img_style['size'] = 2 node.img_style['shape'] = "square" node.img_style['fgcolor'] = "steelblue" ftype_pos = defaultdict(int) for findex, f in enumerate(FACES): if (f['nodetype'] == 'any' or (f['nodetype'] == 'leaf' and node.is_leaf()) or (f['nodetype'] == 'internal' and not node.is_leaf())): # if node passes face filters if node_matcher(node, f["filters"]): if f["value"].startswith("@"): fvalue = getattr(node, f["value"][1:], None) else: fvalue = f["value"] # if node's attribute has content, generate face if fvalue is not None: fsize = f["size"] fbgcolor = f["bgcolor"] fcolor = f['color'] if fcolor: # Parse color options auto_m = re.search("auto\(([^)]*)\)", fcolor) if auto_m: target_attr = auto_m.groups()[0].strip() if not target_attr: color_keyattr = f["value"] else: color_keyattr = target_attr color_keyattr = color_keyattr.lstrip('@') color_bin = getattr( node, color_keyattr, None) last_seed = f2last_seed.setdefault( color_keyattr, random.random()) seed = last_seed + 0.10 + random.uniform( 0.1, 0.2) f2last_seed[color_keyattr] = seed fcolor = f2color.setdefault( color_bin, random_color(h=seed)) if fbgcolor: # Parse color options auto_m = re.search("auto\(([^)]*)\)", fbgcolor) if auto_m: target_attr = auto_m.groups()[0].strip() if not target_attr: color_keyattr = f["value"] else: color_keyattr = target_attr color_keyattr = color_keyattr.lstrip('@') color_bin = getattr( node, color_keyattr, None) last_seed = f2last_seed.setdefault( color_keyattr, random.random()) seed = last_seed + 0.10 + random.uniform( 0.1, 0.2) f2last_seed[color_keyattr] = seed fbgcolor = f2color.setdefault( color_bin, random_color(h=seed)) if f["ftype"] == "text": if f.get("format", None): fvalue = f["format"] % fvalue F = TextFace(fvalue, fsize=fsize, fgcolor=fcolor or "black", fstyle=f.get('fstyle', None)) elif f["ftype"] == "fullseq": F = faces.SeqMotifFace(seq=fvalue, seq_format="seq", seqtail_format="seq", height=fsize) elif f["ftype"] == "compactseq": F = faces.SeqMotifFace( seq=fvalue, seq_format="compactseq", seqtail_format="compactseq", height=fsize) elif f["ftype"] == "blockseq": F = faces.SeqMotifFace( seq=fvalue, seq_format="blockseq", seqtail_format="blockseq", height=fsize, fgcolor=fcolor or "slategrey", bgcolor=fbgcolor or "slategrey", scale_factor=1.0) fbgcolor = None elif f["ftype"] == "bubble": try: v = float(fvalue) except ValueError: rad = fsize else: rad = fsize * v F = faces.CircleFace(radius=rad, style="sphere", color=fcolor or "steelblue") elif f["ftype"] == "heatmap": if not f['column']: col = ftype_pos[f["pos"]] else: col = f["column"] for i, value in enumerate( heatmap_data.get(node.name, [])): ftype_pos[f["pos"]] += 1 if value is None: color = heatmap_color_missing elif value > heatmap_center_value: color = gradient_color( abs(heatmap_center_value - value), heatmap_max_value, hue=heatmap_color_up) elif value < heatmap_center_value: color = gradient_color( abs(heatmap_center_value - value), heatmap_max_value, hue=heatmap_color_down) else: color = heatmap_color_center node.add_face(RectFace( 20, 20, color, color), position="aligned", column=col + i) # Add header # for i, name in enumerate(header): # nameF = TextFace(name, fsize=7) # nameF.rotation = -90 # tree_style.aligned_header.add_face(nameF, column=i) F = None elif f["ftype"] == "profile": # internal profiles? F = None elif f["ftype"] == "barchart": F = None elif f["ftype"] == "piechart": F = None # Add the Face if F: F.opacity = f['opacity'] or 1.0 # Set face general attributes if fbgcolor: F.background.color = fbgcolor if not f['column']: col = ftype_pos[f["pos"]] ftype_pos[f["pos"]] += 1 else: col = f["column"] node.add_face(F, column=col, position=f["pos"]) if args.image: t.render("t%d.%s" % (tindex, args.image), tree_style=ts, w=args.width, h=args.height, units=args.size_units) else: t.show(None, tree_style=ts)
def layout(self, node): #if not node.is_leaf(): scale=self.scaling eps = .000000001 node_taxid = str(node.taxid) if node_taxid in self.profile_tax_id_to_percentage and self.profile_tax_id_to_percentage[node_taxid] > 0.: if (scale=="log"): size_profile = np.log(self.profile_tax_id_to_percentage[node_taxid]) elif(scale=="sqrt"): size_profile = np.sqrt(self.profile_tax_id_to_percentage[node_taxid]) elif(scale=="exponent"): size_profile = np.exp(self.profile_tax_id_to_percentage[node_taxid]) elif(scale=="linear"): size_profile = (self.profile_tax_id_to_percentage[node_taxid]) else: size_profile = eps if node_taxid in self.ground_truth_tax_id_to_percentage and self.ground_truth_tax_id_to_percentage[node_taxid] > 0.: if (scale=="log"): size_ground_truth = np.log(self.ground_truth_tax_id_to_percentage[node_taxid]) elif(scale=="sqrt"): size_ground_truth = np.sqrt(self.ground_truth_tax_id_to_percentage[node_taxid]) elif(scale=="exponent"): size_ground_truth = np.exp(self.ground_truth_tax_id_to_percentage[node_taxid]) elif(scale=="linear"): size_ground_truth = (self.ground_truth_tax_id_to_percentage[node_taxid]) else: size_ground_truth = eps size = 25*max([size_ground_truth, size_profile]) chart_sizes = np.array([size_profile, size_ground_truth]) # print(np.sum(chart_sizes)) if not np.sum(chart_sizes) == 0: chart_sizes = 100 * (chart_sizes / np.sum(chart_sizes)) if(self.labels=="All"): F2 = TextFace(abbreaviate_name(node.sci_name), tight_text=True, fsize=20) # use the scientific name faces.add_face_to_node(F2, node, column=0, position="branch-right") elif(self.labels=="Leaf"): if node.is_leaf(): F2 = TextFace(abbreaviate_name(node.sci_name), tight_text=True, fsize=20) # use the scientific name faces.add_face_to_node(F2, node, column=0, position="branch-right") # print(chart_sizes) if(self.layt=="Pie"): # PIE CHART F = faces.PieChartFace(chart_sizes,colors=['#1b9e77', '#d95f02'],width=size, height=size) elif(self.layt=="Bar"):# BAR CHART F = faces.BarChartFace(chart_sizes, deviations=None, labels=None, colors=['#1b9e77', '#d95f02'],width=50, height=50, label_fsize=0, scale_fsize=0) #print(chart_sizes, node.sci_name) elif(self.layt=="Circle"): #TWO CIRCLES SIDE BY SIDE F=faces.CircleFace(radius=size_profile*10, color="#1b9e77", style='circle', label=None) F1=faces.CircleFace(radius=size_ground_truth*10, color="#d95f02", style='circle', label=None) F1.border.width = None F1.opacity = 0.6 faces.add_face_to_node(F1, node, 0, position="float-behind") elif(self.layt=="Rectangle"): #TWO CIRCLES SIDE BY SIDE F=faces.RectFace(width=size_profile*40, height=40, fgcolor="#1b9e77",bgcolor="#1b9e77", label=None) F1=faces.RectFace(width=size_ground_truth*40, height=40, fgcolor="#d95f02",bgcolor="#d95f02", label=None) F1.border.width = None F1.opacity = 0.6 faces.add_face_to_node(F1, node, 0, position="float-behind") faces.add_face_to_node(F, node, 0, position="float-behind") F.border.width = None F.opacity = 0.6