Skip to content

Commit

Permalink
domain_layouts.py: Simplify things and do not load big json files jus…
Browse files Browse the repository at this point in the history
…t to import the module.

This still needs more cleanup, but at least it will not make ete choke
like before!
  • Loading branch information
jordibc committed Nov 3, 2023
1 parent 6cd27cf commit 5c20350
Showing 1 changed file with 41 additions and 67 deletions.
108 changes: 41 additions & 67 deletions ete4/smartview/renderer/layouts/domain_layouts.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# TODO: This file needs reviewing. No need to do all this just to get
# classes LayoutPfamDomains and LayoutSmartDomains.
import os
import json

Expand All @@ -8,103 +10,75 @@
from ete4.config import ETE_DATA_HOME, update_ete_data


pfam2color_file = ETE_DATA_HOME + '/pfam2color.json'

if not os.path.exists(pfam2color_file):
url = ('https://github.com/etetoolkit/ete-data/raw/main'
'/layouts/pfam2color.json')
update_ete_data(pfam2color_file, url)

with open(pfam2color_file) as handle:
_pfam2color = json.load(handle)


smart2color_file = ETE_DATA_HOME + '/smart2color.json'

if not os.path.exists(smart2color_file):
url = ('https://github.com/etetoolkit/ete-data/raw/main'
'/layouts/smart2color.json')
update_ete_data(smart2color_file, url)

with open(smart2color_file) as handle:
_smart2color = json.load(handle)


class _LayoutDomains(TreeLayout):
def __init__(self, prop, name,
column=10, colormap={},
min_fsize=4, max_fsize=15,
padding_x=5, padding_y=0):
def __init__(self, prop, name, column=10, min_fsize=4, max_fsize=15,
padding_x=5, padding_y=0):
super().__init__(name or "Domains layout")
self.prop = prop
self.column = column
self.aligned_faces = True
self.colormap = colormap
self.min_fsize = min_fsize
self.max_fsize = max_fsize
self.padding = Padding(padding_x, padding_y)

# Load colormap from file if necessary.
color_file = ETE_DATA_HOME + f'/{prop}2color.json'

if not os.path.exists(color_file):
url = ('https://github.com/etetoolkit/ete-data/raw/main'
f'/layouts/{prop}2color.json')
update_ete_data(color_file, url)

with open(color_file) as handle:
self.colormap = json.load(handle)

def get_doms(self, node):
if node.is_leaf:
return node.props.get(self.prop, [])
else:
first_node = next(node.iter_leaves())
return first_node.props.get(self.prop, [])
leaf = next(node.leaves()) # 1st leaf
return leaf.props.get(self.prop, [])

def parse_doms(self, dom_list):
doms = []
for name, start, end in dom_list:
color = self.colormap.get(name, "lightgray")
dom = [int(start), int(end), "()",
None, None, color, color,
"arial|20|black|%s" %(name)]
doms.append(dom)
return doms
def translate(dom):
name, start, end = dom
color = self.colormap.get(name, 'lightgray')
return [int(start), int(end), '()', None, None, color, color,
f'arial|20|black|{name}']

return [translate(dom) for dom in dom_list]

def set_node_style(self, node):
dom_list = self.get_doms(node)
doms = self.parse_doms(dom_list)
fake_seq = '-' * int(node.props.get("len_alg", 0))
doms = self.parse_doms(self.get_doms(node))
fake_seq = '-' * int(node.props.get('len_alg', 0))
if doms or fake_seq:
seqFace = SeqMotifFace(seq=fake_seq, motifs=doms, width=250,
height=10)
node.add_face(seqFace, column=self.column,
position="aligned",
collapsed_only=(not node.is_leaf))
seqFace = SeqMotifFace(seq=fake_seq, motifs=doms, width=250, height=10)
node.add_face(seqFace, column=self.column, position='aligned',
collapsed_only=(not node.is_leaf))


def create_domain_layout(prop, name, colormap, active, column):
# branch_right; column 2; color black
def create_domain_layout(prop, name, active, column):
"""Add a layout named Layout<name> to the globals, and return it."""
# Because this is the wild west, apparently.
class Layout(_LayoutDomains):
def __init__(self,
prop=prop,
name=name,
colormap=colormap,
column=column,
*args, **kwargs):
super().__init__(
prop=prop,
name=name,
colormap=colormap,
column=column,
*args, **kwargs)
def __init__(self, prop=prop, name=name, column=column, *args, **kwargs):
super().__init__(prop=prop, name=name, column=column, *args, **kwargs)
self.active = active

def __name__(self):
return layout_name

# Let's play with the environment like there's no tomorrow!
layout_name = "Layout" + cased_name(name)
Layout.__name__ = layout_name
globals()[layout_name] = Layout
return Layout


domain_layout_args = [
[ "pfam", "Pfam domains", _pfam2color, True ],
[ "smart", "Smart domains", _smart2color, False ],
]
["pfam", "Pfam domains", True],
["smart", "Smart domains", False],
]

col0 = 20
domain_layouts = [ create_domain_layout(*args, i+col0)\
for i, args in enumerate(domain_layout_args) ]
domain_layouts = [create_domain_layout(*args, i+col0)
for i, args in enumerate(domain_layout_args)]

__all__ = [ *[layout.__name__ for layout in domain_layouts] ]

0 comments on commit 5c20350

Please sign in to comment.