Coverage for test_plot.py: 97%

227 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-08-07 10:27 +0200

1 

2import sys 

3import os 

4import tarfile 

5import requests 

6import time 

7import json 

8from collections import defaultdict 

9import unittest 

10 

11sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/..')) 

12 

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 

19 

20paried_color = ["red", "darkblue", "lightgreen", "sienna", "lightCoral", "violet", "mediumturquoise", "lightSkyBlue", "indigo", "tan", "coral", "olivedrab", "teal", "darkyellow"] 

21 

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() 

31 

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 

38 

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) 

44 

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) 

54 

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())  

74 

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) 

82 

83 self.assertEqual(str(layouts[0].__dict__), expected_layout) 

84 

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())  

104 

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) 

112 

113 self.assertEqual(str(layouts[0].__dict__), expected_layout) 

114 

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())  

134 

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) 

142 

143 self.assertEqual(str(layouts[0].__dict__), expected_layout) 

144 

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 

170 

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) 

196 

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) 

222 

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) 

238 

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) 

256 

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) 

276 

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) 

291 

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__ 

299 

300 self.assertEqual(str(layout_dict), expected_layout) 

301 

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) 

324 

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 = {} 

334 

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 

343 

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) 

353 

354 

355 taxa_layout = taxon_layouts.TaxaClade(name='TaxaClade_'+rank, level=level, rank = rank, color_dict=color_dict) 

356 taxa_layouts.append(taxa_layout) 

357 

358 

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 

363 

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 

372 

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) 

379 

380if __name__ == '__main__': 

381 unittest.main() 

382#pytest.main(['-v'])