Coverage for /home/deng/Projects/ete4/hackathon/ete4/ete4/smartview/renderer/layouts/domain_layouts.py: 45%
51 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
1# TODO: This file needs reviewing. No need to do all this just to get
2# classes LayoutPfamDomains and LayoutSmartDomains.
3import os
4import json
6from ..treelayout import TreeLayout, cased_name
7from ..faces import SeqMotifFace
8from ..draw_helpers import Padding
10from ete4.config import ETE_DATA_HOME, update_ete_data
13class _LayoutDomains(TreeLayout):
14 def __init__(self, prop, name, column=10, min_fsize=4, max_fsize=15,
15 padding_x=5, padding_y=0):
16 super().__init__(name or "Domains layout")
17 self.prop = prop
18 self.column = column
19 self.aligned_faces = True
20 self.min_fsize = min_fsize
21 self.max_fsize = max_fsize
22 self.padding = Padding(padding_x, padding_y)
24 # Load colormap from file if necessary.
25 color_file = ETE_DATA_HOME + f'/{prop}2color.json'
27 if not os.path.exists(color_file):
28 url = ('https://github.com/etetoolkit/ete-data/raw/main'
29 f'/layouts/{prop}2color.json')
30 update_ete_data(color_file, url)
32 with open(color_file) as handle:
33 self.colormap = json.load(handle)
35 def get_doms(self, node):
36 leaf = next(node.leaves()) # 1st leaf
37 return leaf.props.get(self.prop, [])
39 def parse_doms(self, dom_list):
40 def translate(dom):
41 name, start, end = dom
42 color = self.colormap.get(name, 'lightgray')
43 return [int(start), int(end), '()', None, None, color, color,
44 f'arial|20|black|{name}']
46 return [translate(dom) for dom in dom_list]
48 def set_node_style(self, node):
49 doms = self.parse_doms(self.get_doms(node))
50 fake_seq = '-' * int(node.props.get('len_alg', 0))
51 if doms or fake_seq:
52 seqFace = SeqMotifFace(seq=fake_seq, motifs=doms, width=250, height=10)
53 node.add_face(seqFace, column=self.column, position='aligned',
54 collapsed_only=(not node.is_leaf))
57def create_domain_layout(prop, name, active, column):
58 """Add a layout named Layout<name> to the globals, and return it."""
59 # Because this is the wild west, apparently.
60 class Layout(_LayoutDomains):
61 def __init__(self, prop=prop, name=name, column=column, *args, **kwargs):
62 super().__init__(prop=prop, name=name, column=column, *args, **kwargs)
63 self.active = active
65 def __name__(self):
66 return layout_name
68 # Let's play with the environment like there's no tomorrow!
69 layout_name = "Layout" + cased_name(name)
70 Layout.__name__ = layout_name
71 globals()[layout_name] = Layout
72 return Layout
75domain_layout_args = [
76 ["pfam", "Pfam domains", True],
77 ["smart", "Smart domains", False],
78]
80col0 = 20
81domain_layouts = [create_domain_layout(*args, i+col0)
82 for i, args in enumerate(domain_layout_args)]
84__all__ = [ *[layout.__name__ for layout in domain_layouts] ]