Coverage for /home/deng/Projects/metatree_drawer/metatreedrawer/treeprofiler/layouts/seq_layouts.py: 36%
86 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-07 10:33 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-07 10:33 +0200
2from ete4 import SeqGroup
3from ete4.smartview import TreeLayout
4from ete4.smartview import AlignmentFace, SeqMotifFace, ScaleFace
5from ete4.smartview.renderer import draw_helpers
6#from utils import get_consensus_seq
7from pathlib import Path
8from io import StringIO
9import json
12__all__ = [ "LayoutAlignment" ]
13DOMAIN2COLOR = 'pfam2color.json' # smart2color.json
15def get_colormap():
16 with open(Path(__file__).parent / DOMAIN2COLOR) as handle:
17 _pfam2color = json.load(handle)
18 return _pfam2color
20class LayoutAlignment(TreeLayout):
21 def __init__(self, name="Alignment",
22 alignment=None, alignment_prop=None, format='seq', width=700, height=15,
23 column=0, scale_range=None, summarize_inner_nodes=True, aligned_faces=True):
24 super().__init__(name, aligned_faces=aligned_faces)
25 #self.alignment = SeqGroup(alignment) if alignment else None
26 self.alignment_prop = alignment_prop
27 self.width = width
28 self.height = height
29 self.column = column
30 self.aligned_faces = True
31 self.format = format
33 #self.length = len(next(self.alignment.iter_entries())[1]) if self.alignment else None
34 self.scale_range = (0, scale_range) or (0, self.length)
35 self.summarize_inner_nodes = summarize_inner_nodes
37 def set_tree_style(self, tree, tree_style):
38 if self.scale_range:
39 face = ScaleFace(width=self.width, scale_range=self.scale_range, padding_y=10)
40 tree_style.aligned_panel_header.add_face(face, column=self.column)
42 def _get_seq(self, node):
43 return node.props.get(self.alignment_prop, None)
44 # if self.alignment:
45 # return self.alignment.get_seq(node.name)
46 # else:
47 # return node.props.get(alignment_prop, None)
49 def get_seq(self, node):
50 if node.is_leaf:
51 return self._get_seq(node)
53 if self.summarize_inner_nodes:
54 return self._get_seq(node)
55 else:
56 first_leaf = next(node.leaves())
57 return self._get_seq(first_leaf)
59 def set_node_style(self, node):
60 seq = self.get_seq(node)
62 if seq:
63 seq = str(seq) # convert Bio.seq.seq to string seq
64 seqFace = AlignmentFace(seq, seq_format=self.format, bgcolor='grey',
65 width=self.width, height=self.height)
66 node.add_face(seqFace, column=self.column, position='aligned',
67 collapsed_only=(not node.is_leaf))
70def get_alnface(seq_prop, level):
71 def layout_fn(node):
72 if node.is_leaf:
73 seq = node.props.get(seq_prop)
74 seq_face = AlignmentFace(seq, seqtype='aa',
75 gap_format='line', seq_format='[]',
76 width=None, height=None, # max height
77 fgcolor='black', bgcolor='#bcc3d0', gapcolor='gray',
78 gap_linewidth=0.2,
79 max_fsize=12, ftype='sans-serif',
80 padding_x=0, padding_y=0)
81 node.add_face(seq_face, position="aligned", column=level)
82 return layout_fn
84class LayoutDomain(TreeLayout):
85 def __init__(self, prop, name,
86 column=10, colormap={},
87 min_fsize=4, max_fsize=15,
88 padding_x=5, padding_y=0):
89 super().__init__(name or "Domains layout")
90 self.prop = prop
91 self.column = column
92 self.aligned_faces = True
93 self.min_fsize = min_fsize
94 self.max_fsize = max_fsize
95 self.padding = draw_helpers.Padding(padding_x, padding_y)
96 if not colormap:
97 self.colormap = get_colormap()
98 else:
99 self.colormap = colormap
101 def get_doms(self, node):
102 pair_delimiter = "@"
103 item_seperator = "||"
104 dom_list = []
105 if node.is_leaf:
106 dom_prop = node.props.get(self.prop, [])
107 if dom_prop:
109 dom_list = [dom.split(pair_delimiter) for dom in dom_prop.split(item_seperator)]
110 #print(dom_list)
111 return dom_list
112 #return node.props.get(self.prop, [])
113 # else:
114 # first_node = next(node.leaves())
115 # print("here", first_node.props.get(self.prop, []))
116 # return first_node.props.get(self.prop, [])
118 def parse_doms(self, dom_list):
119 doms = []
120 for name, start, end in dom_list:
121 color = self.colormap.get(name, "lightgray")
122 dom = [int(start), int(end), "()",
123 None, None, color, color,
124 "arial|30|black|%s" %(name)]
125 doms.append(dom)
126 return doms
128 def set_node_style(self, node):
129 dom_list = self.get_doms(node)
130 if dom_list:
131 doms = self.parse_doms(dom_list)
132 fake_seq = '-' * int(node.props.get("len_alg", 0))
133 if doms or fake_seq:
134 seqFace = SeqMotifFace(seq=fake_seq, motifs=doms, width=400,
135 height=30)
136 node.add_face(seqFace, column=self.column,
137 position="aligned",
138 collapsed_only=(not node.is_leaf))