Coverage for test_plot.py: 97%
227 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-07 10:27 +0200
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-07 10:27 +0200
2import sys
3import os
4import tarfile
5import requests
6import time
7import json
8from collections import defaultdict
9import unittest
11sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/..'))
13from multiprocessing import Process
14from treeprofiler import tree_plot
15from treeprofiler.layouts import (
16 text_layouts, taxon_layouts, staple_layouts,
17 conditional_layouts, seq_layouts, profile_layouts)
18from treeprofiler.src import utils
20paried_color = ["red", "darkblue", "lightgreen", "sienna", "lightCoral", "violet", "mediumturquoise", "lightSkyBlue", "indigo", "tan", "coral", "olivedrab", "teal", "darkyellow"]
22def get_parallel(tree, layouts, expected_draw, expected_config):
23 p1 = Process(target=tree_session, args=(tree, layouts))
24 p2 = Process(target=exam_tree, args=(expected_draw,expected_config))
25 p1.start()
26 time.sleep(1)
27 p2.start()
28 time.sleep(2)
29 p1.terminate()
30 p1.join()
32def exam_tree(expected_draw, expected_config):
33 url = 'http://127.0.0.1:5002/'
34 response1 = requests.get(url+'trees/0/draw')
35 response2 = requests.get(url+'layouts/0')
36 # assert str(json.loads(response2.text)) == expected_config
37 # assert str(json.loads(response1.text)) == expected_draw
39def tree_session(tree, layouts):
40 #t = Tree(TREEFILE, format=1)
41 tree.explore(layouts=layouts, show_leaf_name=True,
42 show_branch_length=True, show_branch_support=True, port=5002,
43 keep_server=True, open_browser=False)
45class TestTreePlots(unittest.TestCase):
46 def test_plot_01(self):
47 # basic annotate categorical data
48 # load tree
49 test_tree = utils.ete4_parse('(a);')
50 layouts = []
51 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False}}"
52 expected_draw = "[['line', [0, 0.5], [1.0, 0.5], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 1.0, 1.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
53 get_parallel(test_tree, layouts, expected_draw, expected_config)
55 def test_plot_02(self):
56 # label_layout
57 newick = "(A:1[&&NHX:alphabet_type=vowel],(B:1[&&NHX:alphabet_type=consonant],(E:1[&&NHX:alphabet_type=vowel],D:1[&&NHX:alphabet_type=consonant])Internal_1:0.5[&&NHX:alphabet_type_counter=consonant--1||vowel--1])Internal_2:0.5[&&NHX:alphabet_type_counter=consonant--2||vowel--1]);"
58 test_tree = utils.ete4_parse(newick)
59 level = 1
60 prop2type = {# start with leaf name
61 'name':str,
62 'dist':float,
63 'support':float,
64 'rank': str,
65 'sci_name': str,
66 'taxid': str,
67 'lineage':str,
68 'named_lineage': str,
69 'evoltype': str,
70 'dup_sp': str,
71 'dup_percent': float,
72 }
73 #popup_prop_keys = list(prop2type.keys())
75 label_layouts, level, color_dict = tree_plot.get_label_layouts(test_tree, ["alphabet_type"], level, prop2type=prop2type)
76 layouts = []
77 layouts.extend(label_layouts)
78 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Label_alphabet_type': True}}"
79 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
80 expected_layout = "{'name': 'Label_alphabet_type', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'text_prop': 'alphabet_type', 'column': 1, 'color_dict': {'consonant': '#9a312f', 'vowel': '#9b57d0'}, 'internal_prop': 'alphabet_type_counter', 'width': 70, 'height': None, 'min_fsize': 5, 'max_fsize': 15, 'absence_color': '#EBEBEB', 'padding_x': 1, 'padding_y': 0}"
81 get_parallel(test_tree, layouts, expected_draw, expected_config)
83 self.assertEqual(str(layouts[0].__dict__), expected_layout)
85 def test_plot_03(self):
86 # label_layout
87 newick = "(A:1[&&NHX:alphabet_type=vowel],(B:1[&&NHX:alphabet_type=consonant],(E:1[&&NHX:alphabet_type=vowel],D:1[&&NHX:alphabet_type=consonant])Internal_1:0.5[&&NHX:alphabet_type_counter=consonant--1||vowel--1])Internal_2:0.5[&&NHX:alphabet_type_counter=consonant--2||vowel--1]);"
88 test_tree = utils.ete4_parse(newick)
89 level = 1
90 prop2type = {# start with leaf name
91 'name':str,
92 'dist':float,
93 'support':float,
94 'rank': str,
95 'sci_name': str,
96 'taxid': str,
97 'lineage':str,
98 'named_lineage': str,
99 'evoltype': str,
100 'dup_sp': str,
101 'dup_percent': float,
102 }
103 #popup_prop_keys = list(prop2type.keys())
105 colorbranch_layouts, level, color_dict = tree_plot.get_colorbranch_layouts(test_tree, ["alphabet_type"], level, prop2type=prop2type)
106 layouts = []
107 layouts.extend(colorbranch_layouts)
108 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Colorbranch_alphabet_type': True}}"
109 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
110 expected_layout = "{'name': 'Colorbranch_alphabet_type', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'text_prop': 'alphabet_type', 'column': 1, 'color_dict': {'consonant': '#9a312f', 'vowel': '#9b57d0'}, 'internal_prop': 'alphabet_type_counter', 'height': None, 'absence_color': '#EBEBEB', 'width': 70, 'padding_x': 1, 'padding_y': 0}"
111 get_parallel(test_tree, layouts, expected_draw, expected_config)
113 self.assertEqual(str(layouts[0].__dict__), expected_layout)
115 def test_plot_04(self):
116 # label_layout
117 newick = "(A:1[&&NHX:alphabet_type=vowel],(B:1[&&NHX:alphabet_type=consonant],(E:1[&&NHX:alphabet_type=vowel],D:1[&&NHX:alphabet_type=consonant])Internal_1:0.5[&&NHX:alphabet_type_counter=consonant--1||vowel--1])Internal_2:0.5[&&NHX:alphabet_type_counter=consonant--2||vowel--1]);"
118 test_tree = utils.ete4_parse(newick)
119 level = 1
120 prop2type = {# start with leaf name
121 'name':str,
122 'dist':float,
123 'support':float,
124 'rank': str,
125 'sci_name': str,
126 'taxid': str,
127 'lineage':str,
128 'named_lineage': str,
129 'evoltype': str,
130 'dup_sp': str,
131 'dup_percent': float,
132 }
133 #popup_prop_keys = list(prop2type.keys())
135 rectangular_layouts, level, color_dict = tree_plot.get_rectangle_layouts(test_tree, ["alphabet_type"], level, prop2type=prop2type)
136 layouts = []
137 layouts.extend(rectangular_layouts)
138 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Rectangular_alphabet_type': True}}"
139 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
140 expected_layout = "{'name': 'Rectangular_alphabet_type', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'text_prop': 'alphabet_type', 'column': 1, 'color_dict': {'consonant': '#9a312f', 'vowel': '#9b57d0'}, 'absence_color': '#EBEBEB', 'internal_prop': 'alphabet_type_counter', 'width': 70, 'height': None, 'min_fsize': 5, 'max_fsize': 15, 'padding_x': 1, 'padding_y': 0}"
141 get_parallel(test_tree, layouts, expected_draw, expected_config)
143 self.assertEqual(str(layouts[0].__dict__), expected_layout)
145 def test_plot_05(self):
146 newick = '(A:1[&&NHX:bool_type=True],(B:1[&&NHX:bool_type=False],(E:1[&&NHX:bool_type=False],D:1[&&NHX:bool_type=True])N4:0.5[&&NHX:bool_type_counter=False--1||True--1])N5:0.5[&&NHX:bool_type_counter=False--2||True--1]);'
147 test_tree = utils.ete4_parse(newick)
148 level = 1
149 prop2type = {# start with leaf name
150 'name':str,
151 'dist':float,
152 'support':float,
153 'rank': str,
154 'sci_name': str,
155 'taxid': str,
156 'lineage':str,
157 'named_lineage': str,
158 'evoltype': str,
159 'dup_sp': str,
160 'dup_percent': float,
161 }
162 binary, level, color_dict = tree_plot.get_binary_layouts(test_tree, ["bool_type"], level, prop2type=prop2type)
163 layouts = []
164 layouts.extend(binary)
165 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Binary_bool_type': True}}"
166 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
167 #expected_layout = "{'name': 'Binary_bool_type', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'bool_prop': 'bool_type', 'column': 1, 'color': '#9f3fbf', 'negative_color': '#EBEBEB', 'prop_colour_dict': {'False': 'red', 'True': 'darkblue'}, 'internal_prop': 'bool_type_counter', 'reverse': False, 'radius': 25, 'padding_x': 1, 'padding_y': 0, 'width': 70, 'height': None, 'min_fsize': 5, 'max_fsize': 10}"
168 get_parallel(test_tree, layouts, expected_draw, expected_config)
169 #assert str(layouts[0].__dict__) == expected_layout
171 def test_plot_06(self):
172 newick = "(A:1[&&NHX:col1=1.0],(B:1[&&NHX:col1=2.0],(E:1[&&NHX:col1=4.0],D:1[&&NHX:col1=3.0])Internal_1:0.5[&&NHX:col1_avg=3.5:col1_max=4.0:col1_min=3.0:col1_std=0.5:col1_sum=7.0])Internal_2:0.5[&&NHX:col1_avg=3.0:col1_max=4.0:col1_min=2.0:col1_std=1.0:col1_sum=9.0]);"
173 test_tree = utils.ete4_parse(newick)
174 level = 1
175 prop2type = {# start with leaf name
176 'name':str,
177 'dist':float,
178 'support':float,
179 'rank': str,
180 'sci_name': str,
181 'taxid': str,
182 'lineage':str,
183 'named_lineage': str,
184 'evoltype': str,
185 'dup_sp': str,
186 'dup_percent': float,
187 }
188 heatmap_layouts, level = tree_plot.get_heatmap_layouts(test_tree, ["col1"], level)
189 layouts = []
190 layouts.extend(heatmap_layouts)
191 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Heatmap_col1': True}}"
192 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
193 expected_layout = "{'name': 'Heatmap_col1_min-max', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'heatmap_prop': 'col1', 'internal_prop': 'col1_avg', 'column': 1, 'value_color': {1.0: '#fff5f0', 2.0: '#fca689', 3.0: '#dd2a25', 4.0: '#67000d', 3.5: '#af1117'}, 'value_range': [1.0, 4.0], 'color_range': {1: '#fff5f0', 2: '#ffece4', 3: '#fee4d8', 4: '#fdd7c6', 5: '#fdc7b2', 6: '#fcb79c', 7: '#fca689', 8: '#fc9474', 9: '#fc8464', 10: '#fb7252', 11: '#f96044', 12: '#f34c37', 13: '#ed392b', 14: '#dd2a25', 15: '#cf1c1f', 16: '#be151a', 17: '#af1117', 18: '#9a0c14', 19: '#800610', 20: '#67000d'}, 'absence_color': '#EBEBEB', 'maxval': 4.0, 'minval': 1.0, 'width': 70, 'height': None, 'padding_x': 1, 'padding_y': 0}"
194 get_parallel(test_tree, layouts, expected_draw, expected_config)
195 self.assertEqual(str(layouts[0].__dict__), expected_layout)
197 def test_plot_07(self):
198 newick = "(A:1[&&NHX:col1=1.0],(B:1[&&NHX:col1=2.0],(E:1[&&NHX:col1=4.0],D:1[&&NHX:col1=3.0])Internal_1:0.5[&&NHX:col1_avg=3.5:col1_max=4.0:col1_min=3.0:col1_std=0.5:col1_sum=7.0])Internal_2:0.5[&&NHX:col1_avg=3.0:col1_max=4.0:col1_min=2.0:col1_std=1.0:col1_sum=9.0]);"
199 test_tree = utils.ete4_parse(newick)
200 level = 1
201 prop2type = {# start with leaf name
202 'name':str,
203 'dist':float,
204 'support':float,
205 'rank': str,
206 'sci_name': str,
207 'taxid': str,
208 'lineage':str,
209 'named_lineage': str,
210 'evoltype': str,
211 'dup_sp': str,
212 'dup_percent': float,
213 }
214 barplot_layouts, level, color_dict = tree_plot.get_barplot_layouts(test_tree, ["col1"], level, prop2type)
215 layouts = []
216 layouts.extend(barplot_layouts)
217 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Barplot_col1': True}}"
218 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
219 expected_layout = "{'name': 'Barplot_col1', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'width': 70, 'position': 'aligned', 'column': 1, 'scale': True, 'padding_x': 10, 'padding_y': 0, 'internal_rep': 'avg', 'prop': 'col1', 'size_prop': 'col1', 'color_prop': None, 'size_range': [0, 4.0], 'color': '#9b57d0', 'colors': None, 'color_gradient': None}"
220 get_parallel(test_tree, layouts, expected_draw, expected_config)
221 self.assertEqual(str(layouts[0].__dict__), expected_layout)
223 def test_plot_08(self):
224 newick = '(A:1[&&NHX:alignment=MAEIPDETIQQFMALT---HNIAVQYLSEFGDLNEALNSYYASQTDDIKDRREEAH],(B:1[&&NHX:alignment=MAEIPDATIQQFMALTNVSHNIAVQY--EFGDLNEALNSYYAYQTDDQKDRREEAH],(E:1[&&NHX:alignment=MAEIPDATIQ---ALTNVSHNIAVQYLSEFGDLNEALNSYYASQTDDQPDRREEAH],D:1[&&NHX:alignment=MAEAPDETIQQFMALTNVSHNIAVQYLSEFGDLNEAL--------------REEAH])Internal_1:0.5[&&NHX:alignment=MAE-PD-TIQQFMALTNVSHNIAVQYLSEFGDLNEALNSYYASQTDDQPDRREEAH])Internal_2:0.5[&&NHX:alignment=MAE-PD-TIQQFMALTNVSHNIAVQYLSEFGDLNEALNSYYA-QTDDQ-DRREEAH])Root:0[&&NHX:alignment=MAEIPD-TIQQFMALTNVSHNIAVQYLSEFGDLNEALNSYYA-QTDD--DRREEAH];'
225 test_tree = utils.ete4_parse(newick)
226 level = 1
227 lengh = len(max(utils.children_prop_array(test_tree, 'alignment'),key=len))
228 aln_layout = seq_layouts.LayoutAlignment(name='Alignment_layout',
229 alignment_prop='alignment', column=level, scale_range=lengh,
230 summarize_inner_nodes=True)
231 layouts = []
232 layouts.append(aln_layout)
233 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Alignment_layout': True}}"
234 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
235 expected_layout = "{'name': 'Alignment_layout', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'alignment_prop': 'alignment', 'width': 700, 'height': 15, 'column': 1, 'format': 'seq', 'scale_range': (0, 56), 'summarize_inner_nodes': True}"
236 get_parallel(test_tree, layouts, expected_draw, expected_config)
237 self.assertEqual(str(layouts[0].__dict__), expected_layout)
239 def test_plot_09(self):
240 # label_layout
241 newick = "(A:1[&&NHX:alphabet_type=vowel],(B:1[&&NHX:alphabet_type=consonant],(E:1[&&NHX:alphabet_type=vowel],D:1[&&NHX:alphabet_type=consonant])Internal_1:0.5[&&NHX:alphabet_type_counter=consonant--1||vowel--1])Internal_2:0.5[&&NHX:alphabet_type_counter=consonant--2||vowel--1]);"
242 test_tree = utils.ete4_parse(newick)
243 level = 1
244 layouts = []
245 profiling_prop = 'alphabet_type'
246 matrix, all_values = tree_plot.single2profile(test_tree, profiling_prop)
247 profile_layout = profile_layouts.LayoutProfile(name=f'Profiling_{profiling_prop}', mode='multi',alignment=matrix, seq_format='profiles', profiles=all_values, column=level, summarize_inner_nodes=True)
248 layouts.append(profile_layout)
249 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Profiling_alphabet_type': True}}"
250 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
251 expected_layout = "{'name': 'Profiling_alphabet_type', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'mode': 'multi', 'width': 40, 'height': 20, 'column': 1, 'seq_format': 'profiles', 'profiles': ['consonant', 'vowel'], 'length': 2, 'scale_range': (0, 2), 'value_range': [], 'value_color': {}, 'summarize_inner_nodes': True}"
252 get_parallel(test_tree, layouts, expected_draw, expected_config)
253 layout_dict = layouts[0].__dict__
254 del layout_dict['alignment']
255 self.assertEqual(str(layout_dict), expected_layout)
257 def test_plot_10(self):
258 # seqgroup is wrong
259 newick = '(A:1[&&NHX:list_data=a|b|c],(B:1[&&NHX:list_data=c|d],(E:1[&&NHX:list_data=e|d|b],D:1[&&NHX:list_data=a|c|d|e])N4:0.5[&&NHX:list_data_counter=a--1||b--1||c--1||d--2||e--2])N5:0.5[&&NHX:list_data_counter=a--1||b--1||c--2||d--3||e--2]);'
260 test_tree = utils.ete4_parse(newick)
261 level = 1
262 layouts = []
263 profiling_prop = 'list_data'
264 matrix, all_values = tree_plot.multiple2profile(test_tree, profiling_prop)
265 profile_layout = profile_layouts.LayoutProfile(name=f'Profiling_{profiling_prop}', mode='multi',
266 alignment=matrix, seq_format='profiles', profiles=all_values, column=level, summarize_inner_nodes=False)
267 level += 1
268 layouts.append(profile_layout)
269 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'Profiling_list_data': True}}"
270 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
271 expected_layout = "{'name': 'Profiling_list_data', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'mode': 'multi', 'width': 80, 'height': 20, 'column': 1, 'seq_format': 'profiles', 'profiles': ['a|b|c', 'a|c|d|e', 'c|d', 'e|d|b'], 'length': 4, 'scale_range': (0, 4), 'value_range': [], 'value_color': {}, 'summarize_inner_nodes': False}"
272 get_parallel(test_tree, layouts, expected_draw, expected_config)
273 layout_dict = layouts[0].__dict__
274 del layout_dict['alignment']
275 self.assertEqual(str(layout_dict), expected_layout)
277 def test_plot_11(self):
278 # categorical to matrix
279 newick = '(A:1[&&NHX:col1=vowel:col2=vowel:col3=1.0:col4=1.0:col5=True:col6=True:col7=a|b|c],(B:1[&&NHX:col1=consonant:col2=consonant:col3=2.0:col4=2.0:col5=False:col6=False:col7=c|d],(E:1[&&NHX:col1=vowel:col2=vowel:col3=4.0:col4=4.0:col5=False:col6=False:col7=e|d|b],D:1[&&NHX:col1=consonant:col2=consonant:col3=3.0:col4=3.0:col5=True:col6=True:col7=a|c|d|e])Internal_1:0.5[&&NHX:col1_counter=consonant--1||vowel--1:col2_counter=consonant--1||vowel--1:col3_avg=3.5:col3_max=4.0:col3_min=3.0:col3_std=0.5:col3_sum=7.0:col4_avg=3.5:col4_max=4.0:col4_min=3.0:col4_std=0.5:col4_sum=7.0:col5_counter=False--1||True--1:col6_counter=False--1||True--1:col7_counter=a--1||b--1||c--1||d--2||e--2])Internal_2:0.5[&&NHX:col1_counter=consonant--2||vowel--1:col2_counter=consonant--2||vowel--1:col3_avg=3.0:col3_max=4.0:col3_min=2.0:col3_std=1.0:col3_sum=9.0:col4_avg=3.0:col4_max=4.0:col4_min=2.0:col4_std=1.0:col4_sum=9.0:col5_counter=False--2||True--1:col6_counter=False--2||True--1:col7_counter=a--1||b--1||c--2||d--3||e--2])Root:0[&&NHX:col1_counter=consonant--2||vowel--2:col2_counter=consonant--2||vowel--2:col3_avg=2.5:col3_max=4.0:col3_min=1.0:col3_std=1.6666666666666667:col3_sum=10.0:col4_avg=2.5:col4_max=4.0:col4_min=1.0:col4_std=1.6666666666666667:col4_sum=10.0:col5_counter=False--2||True--2:col6_counter=False--2||True--2:col7_counter=a--2||b--2||c--3||d--3||e--2];'
280 test_tree = utils.ete4_parse(newick)
281 level = 1
282 layouts = []
283 profiling_props = ['col1', 'col2']
284 matrix, value2color = tree_plot.categorical2matrix(test_tree, profiling_props)
285 # profile_layout = profile_layouts.LayoutProfile(name='categorical_matrix_layout',
286 # mode='single', alignment=matrix, seq_format='categories', profiles=profiling_props,
287 # value_color=value2color, column=level)
288 profile_layout = profile_layouts.LayoutPropsMatrixOld(name='categorical_matrix_layout',
289 matrix=matrix, matrix_type='categorical', matrix_props=profiling_props,
290 value_color=value2color, column=level)
292 level += 1
293 layouts.append(profile_layout)
294 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'categorical_matrix_layout': True}}"
295 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
296 expected_layout = "{'name': 'categorical_matrix_layout', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'matrix': {'A': ['vowel', 'vowel'], 'B': ['consonant', 'consonant'], 'E': ['vowel', 'vowel'], 'D': ['consonant', 'consonant']}, 'matrix_type': 'categorical', 'matrix_props': ['col1', 'col2'], 'is_list': False, 'width': 40, 'height': 20, 'column': 1, 'length': 2, 'scale_range': (0, 2), 'value_range': [], 'value_color': {'consonant': '#9a312f', 'vowel': '#9b57d0'}, 'summarize_inner_nodes': False}"
297 get_parallel(test_tree, layouts, expected_draw, expected_config)
298 layout_dict = layouts[0].__dict__
300 self.assertEqual(str(layout_dict), expected_layout)
302 def test_plot_12(self):
303 # categorical to matrix
304 newick = '(A:1[&&NHX:col1=vowel:col2=vowel:col3=1.0:col4=1.0:col5=True:col6=True:col7=a|b|c],(B:1[&&NHX:col1=consonant:col2=consonant:col3=2.0:col4=2.0:col5=False:col6=False:col7=c|d],(E:1[&&NHX:col1=vowel:col2=vowel:col3=4.0:col4=4.0:col5=False:col6=False:col7=e|d|b],D:1[&&NHX:col1=consonant:col2=consonant:col3=3.0:col4=3.0:col5=True:col6=True:col7=a|c|d|e])Internal_1:0.5[&&NHX:col1_counter=consonant--1||vowel--1:col2_counter=consonant--1||vowel--1:col3_avg=3.5:col3_max=4.0:col3_min=3.0:col3_std=0.5:col3_sum=7.0:col4_avg=3.5:col4_max=4.0:col4_min=3.0:col4_std=0.5:col4_sum=7.0:col5_counter=False--1||True--1:col6_counter=False--1||True--1:col7_counter=a--1||b--1||c--1||d--2||e--2])Internal_2:0.5[&&NHX:col1_counter=consonant--2||vowel--1:col2_counter=consonant--2||vowel--1:col3_avg=3.0:col3_max=4.0:col3_min=2.0:col3_std=1.0:col3_sum=9.0:col4_avg=3.0:col4_max=4.0:col4_min=2.0:col4_std=1.0:col4_sum=9.0:col5_counter=False--2||True--1:col6_counter=False--2||True--1:col7_counter=a--1||b--1||c--2||d--3||e--2])Root:0[&&NHX:col1_counter=consonant--2||vowel--2:col2_counter=consonant--2||vowel--2:col3_avg=2.5:col3_max=4.0:col3_min=1.0:col3_std=1.6666666666666667:col3_sum=10.0:col4_avg=2.5:col4_max=4.0:col4_min=1.0:col4_std=1.6666666666666667:col4_sum=10.0:col5_counter=False--2||True--2:col6_counter=False--2||True--2:col7_counter=a--2||b--2||c--3||d--3||e--2];'
305 test_tree = utils.ete4_parse(newick)
306 level = 1
307 layouts = []
308 profiling_props = ['col3', 'col4']
309 matrix, minval, maxval, _, _, _, _ = tree_plot.numerical2matrix(test_tree, profiling_props)
310 # profile_layout = profile_layouts.LayoutProfile(name='numerical_matrix_layout', mode='numerical',
311 # alignment=matrix, seq_format='gradients', profiles=profiling_props,
312 # value_range=[minval, maxval], column=level)
313 profile_layout = profile_layouts.LayoutPropsMatrixOld(name='numerical_matrix_layout',
314 matrix=matrix, matrix_type='categorical', matrix_props=profiling_props,
315 column=level)
316 level += 1
317 layouts.append(profile_layout)
318 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'numerical_matrix_layout': True}}"
319 expected_draw = "[['line', [0, 2.0], [2.0, 2.0], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 4.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
320 expected_layout = "{'name': 'numerical_matrix_layout', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'matrix': {'Root': [None, None], 'A': [1.0, 1.0], 'Internal_2': [None, None], 'B': [2.0, 2.0], 'Internal_1': [None, None], 'E': [4.0, 4.0], 'D': [3.0, 3.0]}, 'matrix_type': 'categorical', 'matrix_props': ['col3', 'col4'], 'is_list': False, 'width': 40, 'height': 20, 'column': 1, 'length': 2, 'scale_range': (0, 2), 'value_range': [], 'value_color': {}, 'summarize_inner_nodes': False}"
321 get_parallel(test_tree, layouts, expected_draw, expected_config)
322 layout_dict = layouts[0].__dict__
323 self.assertEqual(str(layout_dict), expected_layout)
325 def test_plot_13(self):
326 # taxonomic layouts
327 newick = "((9598.abc:1[&&NHX:common_name=Pan troglodytes:lineage=1|131567|2759|33154|33208|6072|33213|33511|7711|89593|7742|7776|117570|117571|8287|1338369|32523|32524|40674|32525|9347|1437010|314146|9443|376913|314293|9526|314295|9604|207598|9596|9598:named_lineage=root|cellular organisms|Eukaryota|Opisthokonta|Metazoa|Eumetazoa|Bilateria|Deuterostomia|Chordata|Craniata|Vertebrata|Gnathostomata|Teleostomi|Euteleostomi|Sarcopterygii|Dipnotetrapodomorpha|Tetrapoda|Amniota|Mammalia|Theria|Eutheria|Boreoeutheria|Euarchontoglires|Primates|Haplorrhini|Simiiformes|Catarrhini|Hominoidea|Hominidae|Homininae|Pan|Pan troglodytes:rank=species:sci_name=Pan troglodytes:taxid=9598],9606.nca:1[&&NHX:common_name=Homo sapiens:lineage=1|131567|2759|33154|33208|6072|33213|33511|7711|89593|7742|7776|117570|117571|8287|1338369|32523|32524|40674|32525|9347|1437010|314146|9443|376913|314293|9526|314295|9604|207598|9605|9606:named_lineage=root|cellular organisms|Eukaryota|Opisthokonta|Metazoa|Eumetazoa|Bilateria|Deuterostomia|Chordata|Craniata|Vertebrata|Gnathostomata|Teleostomi|Euteleostomi|Sarcopterygii|Dipnotetrapodomorpha|Tetrapoda|Amniota|Mammalia|Theria|Eutheria|Boreoeutheria|Euarchontoglires|Primates|Haplorrhini|Simiiformes|Catarrhini|Hominoidea|Hominidae|Homininae|Homo|Homo sapiens:rank=species:sci_name=Homo sapiens:taxid=9606])Homininae:1[&&NHX:common_name=:lineage=1|131567|2759|33154|33208|6072|33213|33511|7711|89593|7742|7776|117570|117571|8287|1338369|32523|32524|40674|32525|9347|1437010|314146|9443|376913|314293|9526|314295|9604|207598:named_lineage=root|cellular organisms|Eukaryota|Opisthokonta|Metazoa|Eumetazoa|Bilateria|Deuterostomia|Chordata|Craniata|Vertebrata|Gnathostomata|Teleostomi|Euteleostomi|Sarcopterygii|Dipnotetrapodomorpha|Tetrapoda|Amniota|Mammalia|Theria|Eutheria|Boreoeutheria|Euarchontoglires|Primates|Haplorrhini|Simiiformes|Catarrhini|Hominoidea|Hominidae|Homininae:rank=subfamily:sci_name=Homininae:taxid=207598],10090.abd:1[&&NHX:common_name=Mus musculus:lineage=1|131567|2759|33154|33208|6072|33213|33511|7711|89593|7742|7776|117570|117571|8287|1338369|32523|32524|40674|32525|9347|1437010|314146|314147|9989|1963758|337687|10066|39107|10088|862507|10090:named_lineage=root|cellular organisms|Eukaryota|Opisthokonta|Metazoa|Eumetazoa|Bilateria|Deuterostomia|Chordata|Craniata|Vertebrata|Gnathostomata|Teleostomi|Euteleostomi|Sarcopterygii|Dipnotetrapodomorpha|Tetrapoda|Amniota|Mammalia|Theria|Eutheria|Boreoeutheria|Euarchontoglires|Glires|Rodentia|Myomorpha|Muroidea|Muridae|Murinae|Mus|Mus|Mus musculus:rank=species:sci_name=Mus musculus:taxid=10090]);"
328 test_tree = utils.ete4_parse(newick)
329 level = 1
330 layouts = []
331 taxon_color_dict = {}
332 taxa_layouts = []
333 rank2values = {}
335 # generate a rank2values dict for pre taxonomic annotated tree
336 if not rank2values:
337 rank2values = defaultdict(list)
338 for n in test_tree.traverse():
339 if n.props.get('rank') and n.props.get('rank') != 'Unknown':
340 rank2values[n.props.get('rank')].append(n.props.get('sci_name',''))
341 else:
342 pass
344 # assign color for each value of each rank
345 for rank, value in sorted(rank2values.items()):
346 color_dict = {}
347 nvals = len(value)
348 for i in range(0, nvals):
349 if nvals <= 14:
350 color_dict[value[i]] = paried_color[i]
351 else:
352 color_dict[value[i]] = random_color(h=None)
355 taxa_layout = taxon_layouts.TaxaClade(name='TaxaClade_'+rank, level=level, rank = rank, color_dict=color_dict)
356 taxa_layouts.append(taxa_layout)
359 taxa_layout = taxon_layouts.TaxaRectangular(name = "TaxaRect_"+rank, rank=rank ,color_dict=color_dict, column=level)
360 taxa_layouts.append(taxa_layout)
361 #level += 1
362 taxon_color_dict[rank] = color_dict
364 #taxa_layouts.append(taxon_layouts.TaxaRectangular(name = "Last Common Ancester", color_dict=taxon_color_dict, column=level))
365 taxa_layouts.append(taxon_layouts.LayoutSciName(name = 'Taxa Scientific name', color_dict=taxon_color_dict))
366 taxa_layouts.append(taxon_layouts.LayoutEvolEvents(name='Taxa Evolutionary events', prop="evoltype",
367 speciation_color="blue",
368 duplication_color="red", node_size = 2,
369 legend=True))
370 layouts = layouts + taxa_layouts
371 level += 1
373 expected_config = "{'default': {'Branch length': True, 'Branch support': True, 'Leaf name': True, 'Number of leaves': False, 'TaxaClade_species': True, 'TaxaRect_species': True, 'TaxaClade_subfamily': True, 'TaxaRect_subfamily': True, 'Taxa Scientific name': True, 'Taxa Evolutionary events': True}}"
374 expected_draw = "[['line', [0, 1.5], [2.0, 1.5], '', [], {'stroke': '#000000', 'stroke-width': 0.5, 'fill': '#e5e5e5', 'fill-opacity': 0.3, 'type': 'solid'}], ['nodebox', [0, 0, 2.0, 3.0], '', {'name': '', 'dist': 0.0, 'support': 1.0}, [], [], {'fill': 'transparent'}]]"
375 expected_layout = "{'name': 'TaxaClade_species', 'active': True, 'aligned_faces': True, 'description': '', 'legend': True, 'always_render': False, 'ts': None, 'ns': None, 'activate': False, 'column': 1, 'rank': 'species', 'color_dict': {'Mus musculus': 'red', 'Pan troglodytes': 'darkblue', 'Homo sapiens': 'lightgreen'}}"
376 get_parallel(test_tree, layouts, expected_draw, expected_config)
377 layout_dict = layouts[0].__dict__
378 self.assertEqual(str(layout_dict), expected_layout)
380if __name__ == '__main__':
381 unittest.main()
382#pytest.main(['-v'])