Coverage for /home/deng/Projects/ete4/hackathon/ete4/ete4/smartview/renderer/layouts/default_layouts.py: 22%
91 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-03-21 09:19 +0100
« prev ^ index » next coverage.py v7.2.7, created at 2024-03-21 09:19 +0100
1from ..treelayout import TreeLayout
2from ..nodestyle import NodeStyle
3from ..faces import AttrFace, TextFace, OutlineFace, AlignLinkFace
5from ..draw_helpers import summary, Padding
8__all__ = ['LayoutLeafName', 'LayoutNumberLeaves',
9 'LayoutBranchLength', 'LayoutBranchSupport',
10 'LayoutOutline']
13class LayoutLeafName(TreeLayout):
14 def __init__(self, name='Leaf name',
15 pos='branch_right', color='black',
16 ftype='sans-serif',
17 min_fsize=4, max_fsize=15,
18 padding_x=5, padding_y=0):
19 super().__init__(name)
20 self.pos = pos
21 self.aligned_faces = self.pos == 'aligned'
22 self.color = color
23 self.ftype = ftype
24 self.min_fsize = min_fsize
25 self.max_fsize = max_fsize
26 self.padding = Padding(padding_x, padding_y)
28 self.face = AttrFace(
29 attr='name', name='leaf_name',
30 ftype=self.ftype,
31 min_fsize=self.min_fsize, max_fsize=self.max_fsize,
32 color=self.color, padding_x=self.padding.x, padding_y=self.padding.y)
34 def set_node_style(self, node):
35 if node.is_leaf:
36 node.add_face(self.face, position=self.pos, column=1)
37 else:
38 # Collapsed face
39 names = summary(node.children)
40 texts = names if len(names) < 6 else (names[:3] + ['...'] + names[-2:])
41 for i, text in enumerate(texts):
42 node.add_face(TextFace(text, name='leaf_name',
43 color=self.color, ftype=self.ftype,
44 min_fsize=self.min_fsize, max_fsize=self.max_fsize,
45 padding_x=self.padding.x, padding_y=self.padding.y),
46 position=self.pos, column=2, collapsed_only=True)
49class LayoutNumberLeaves(TreeLayout):
50 def __init__(self, name='Number of leaves',
51 pos='branch_right', collapsed_only=True,
52 formatter='(%s)', color='black',
53 min_fsize=4, max_fsize=15, ftype='sans-serif',
54 padding_x=5, padding_y=0):
55 super().__init__(name)
56 self.pos = pos
57 self.aligned_faces = self.pos == 'aligned'
58 self.color = color
59 self.formatter = formatter
60 self.ftype = ftype
61 self.min_fsize = min_fsize
62 self.max_fsize = max_fsize
63 self.padding = Padding(padding_x, padding_y)
65 self.active = False
67 self.collapsed_only = collapsed_only
69 def set_node_style(self, node):
70 if not node.is_leaf:
71 face = TextFace(
72 self.formatter % len(node), # number of leaves
73 color=self.color,
74 min_fsize=self.min_fsize, max_fsize=self.max_fsize,
75 ftype=self.ftype,
76 padding_x=self.padding.x, padding_y=self.padding.y)
78 node.add_face(face, position=self.pos, column=1, collapsed_only=True)
80 if not self.collapsed_only:
81 node.add_face(face, position=self.pos, column=0)
84def _get_layout_branch_attr(attr, pos, name=None,
85 formatter=None, color='black',
86 ftype='sans-serif',
87 min_fsize=6, max_fsize=15,
88 padding_x=0, padding_y=0):
89 branch_attr_face = AttrFace(attr,
90 formatter=formatter,
91 name=name or f'branch_{attr}',
92 color=color, ftype=ftype,
93 min_fsize=min_fsize, max_fsize=max_fsize,
94 padding_x=padding_x,
95 padding_y=padding_y)
97 def layout_fn(node):
98 # Skip adding faces in the following cases:
99 if (attr not in node.props or # missing property
100 node.dist == 0 or # no space for drawing
101 node.is_leaf and attr == 'support'): # should be 1
102 return # do not add faces
104 node.add_face(branch_attr_face, position=pos, column=0)
105 node.add_face(branch_attr_face, position=pos, column=0,
106 collapsed_only=True)
108 return layout_fn
111class LayoutBranchLength(TreeLayout):
112 def __init__(self, name='Branch length',
113 pos='branch_top',
114 formatter='%0.5s',
115 color='#8d8d8d', ftype="sans-serif",
116 min_fsize=6, max_fsize=15,
117 padding_x=2, padding_y=0):
118 super().__init__(name)
119 self.pos = pos
120 self.aligned_faces = self.pos == 'aligned'
121 self.color = color
122 self.formatter = formatter
123 self.ftype = ftype
124 self.min_fsize = min_fsize
125 self.max_fsize = max_fsize
126 self.padding = Padding(padding_x, padding_y)
128 self.set_node_style = _get_layout_branch_attr(attr='dist',
129 formatter=formatter,
130 name='Branch length',
131 pos=pos,
132 color=color, ftype=self.ftype,
133 min_fsize=min_fsize, max_fsize=max_fsize,
134 padding_x=padding_x, padding_y=padding_y)
137class LayoutBranchSupport(TreeLayout):
138 def __init__(self, name='Branch support',
139 pos='branch_bottom',
140 formatter='%0.4s',
141 color='#fa8072', ftype="sans-serif",
142 min_fsize=6, max_fsize=15,
143 padding_x=2,padding_y=0):
144 super().__init__(name)
145 self.pos = pos
146 self.aligned_faces = self.pos == 'aligned'
147 self.color = color
148 self.formatter = formatter
149 self.ftype = ftype
150 self.min_fsize = min_fsize
151 self.max_fsize = max_fsize
152 self.padding = Padding(padding_x, padding_y)
154 self.set_node_style = _get_layout_branch_attr(attr='support',
155 formatter=formatter,
156 name="Branch support",
157 pos=pos,
158 color=color, ftype=self.ftype,
159 min_fsize=min_fsize, max_fsize=max_fsize,
160 padding_x=padding_x, padding_y=padding_y)
163class LayoutOutline(TreeLayout):
164 def __init__(self, name=None,
165 stroke_color="black", stroke_width=0.5,
166 color="lightgray", opacity=0.3, collapsing_height=5):
167 super().__init__(None)
169 self.always_render = True
171 self.face = OutlineFace(stroke_color="black", stroke_width=stroke_width,
172 color=color, opacity=opacity, collapsing_height=collapsing_height)
174 def set_node_style(self, node):
175 if not node.is_leaf:
176 node.add_face(self.face,
177 position="branch_right", column=0,
178 collapsed_only=True)
181def get_layout_align_link(stroke_color='gray', stroke_width=0.5,
182 line_type=1, opacity=0.8):
183 align_link_face = AlignLinkFace(stroke_color=stroke_color,
184 stroke_width=stroke_width,
185 line_type=line_type,
186 opacity=opacity)
187 def layout_fn(node):
188 if node.is_leaf:
189 node.add_face(align_link_face,
190 position='branch_right',
191 column=1e9)
192 else:
193 node.add_face(align_link_face,
194 position='branch_right',
195 column=1e9,
196 collapsed_only=True)
197 layout_fn.__name__ = 'Aligned panel link'
198 layout_fn._module = 'default'
199 return layout_fn