|
4 | 4 | singularity views/trees.py: part of singularity package |
5 | 5 |
|
6 | 6 | ''' |
7 | | - |
| 7 | +from functools import reduce |
8 | 8 | import json |
9 | 9 |
|
10 | 10 | from singularity.logman import bot |
@@ -227,3 +227,63 @@ def make_package_tree(matrix=None,labels=None,width=25,height=10,title=None): |
227 | 227 | leaf_font_size=8., # font size for the x axis labels |
228 | 228 | labels=labels) |
229 | 229 | return plt |
| 230 | + |
| 231 | + |
| 232 | +def make_interactive_tree(matrix=None,labels=None): |
| 233 | + '''make interactive tree will return complete html for an interactive tree |
| 234 | + :param title: a title for the plot, if not defined, will be left out. |
| 235 | + ''' |
| 236 | + from scipy.cluster.hierarchy import ( |
| 237 | + dendrogram, |
| 238 | + linkage, |
| 239 | + to_tree |
| 240 | + ) |
| 241 | + |
| 242 | + d3 = None |
| 243 | + from scipy.cluster.hierarchy import cophenet |
| 244 | + from scipy.spatial.distance import pdist |
| 245 | + |
| 246 | + if isinstance(matrix,pandas.DataFrame): |
| 247 | + Z = linkage(matrix, 'ward') # clusters |
| 248 | + T = to_tree(Z, rd=False) |
| 249 | + |
| 250 | + if labels == None: |
| 251 | + labels = matrix.index.tolist() |
| 252 | + lookup = dict(zip(range(len(labels)), labels)) |
| 253 | + |
| 254 | + # Create a dendrogram object without plotting |
| 255 | + dend = dendrogram(Z,no_plot=True, |
| 256 | + orientation="right", |
| 257 | + leaf_rotation=90., # rotates the x axis labels |
| 258 | + leaf_font_size=8., # font size for the x axis labels |
| 259 | + labels=labels) |
| 260 | + |
| 261 | + d3 = dict(children=[], name="root") |
| 262 | + add_node(T, d3) |
| 263 | + label_tree(d3["children"][0],lookup) |
| 264 | + else: |
| 265 | + bot.logger.warning('Please provide data as pandas Data Frame.') |
| 266 | + return d3 |
| 267 | + |
| 268 | + |
| 269 | +def add_node(node, parent): |
| 270 | + '''add_node will add a node to it's parent |
| 271 | + ''' |
| 272 | + newNode = dict(node_id=node.id, children=[]) |
| 273 | + parent["children"].append(newNode) |
| 274 | + if node.left: add_node(node.left, newNode) |
| 275 | + if node.right: add_node(node.right, newNode) |
| 276 | + |
| 277 | + |
| 278 | +def label_tree(n,lookup): |
| 279 | + '''label tree will again recursively label the tree |
| 280 | + :param n: the root node, usually d3['children'][0] |
| 281 | + :param lookup: the node/id lookup |
| 282 | + ''' |
| 283 | + if len(n["children"]) == 0: |
| 284 | + leaves = [lookup[n["node_id"]]] |
| 285 | + else: |
| 286 | + leaves = reduce(lambda ls, c: ls + label_tree(c,lookup), n["children"], []) |
| 287 | + del n["node_id"] |
| 288 | + n["name"] = name = "-".join(sorted(map(str, leaves))) |
| 289 | + return leaves |
0 commit comments