Skip to content

Commit 7749102

Browse files
committed
adding functions to generate interactive tree - still needs work, but returns basic data object
1 parent 15c38f6 commit 7749102

File tree

3 files changed

+84
-13
lines changed

3 files changed

+84
-13
lines changed

singularity/analysis/compare.py

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ def container_similarity_vector(container1=None,packages_set=None,by=None,custom
7575
return comparisons
7676

7777

78+
7879
def compare_containers(container1=None,container2=None,by=None,
7980
image_package1=None,image_package2=None):
8081
'''compare_containers will generate a data structure with common and unique files to
@@ -105,19 +106,29 @@ def compare_containers(container1=None,container2=None,by=None,
105106
# Do the comparison for each metric
106107
comparisons = dict()
107108
for b in by:
108-
intersect = list(set(container1_guts[b]).intersection(container2_guts[b]))
109-
unique1 = list(set(container1_guts[b]).difference(container2_guts[b]))
110-
unique2 = list(set(container2_guts[b]).difference(container1_guts[b]))
111-
112-
# Return data structure
113-
comparison = {"intersect":intersect,
114-
"unique1": unique1,
115-
"unique2": unique2,
116-
"total1": len(container1_guts[b]),
117-
"total2": len(container2_guts[b])}
118-
comparisons[b] = comparison
109+
comparisons[b] = compare_lists(container1_guts[b],container2_guts[b])
119110

120111
return comparisons
112+
113+
114+
def compare_lists(list1,list2):
115+
'''compare lists is the lowest level that drives compare_containers and
116+
compare_packages. It returns a comparison object (dict) with the unique,
117+
total, and intersecting things between two lists
118+
:param list1: the list for container1
119+
:param list2: the list for container2
120+
'''
121+
intersect = list(set(list1).intersection(list2))
122+
unique1 = list(set(list1).difference(list2))
123+
unique2 = list(set(list2).difference(list1))
124+
125+
# Return data structure
126+
comparison = {"intersect":intersect,
127+
"unique1": unique1,
128+
"unique2": unique2,
129+
"total1": len(list1),
130+
"total2": len(list2)}
131+
return comparison
121132

122133

123134
def calculate_similarity(container1=None,container2=None,image_package1=None,

singularity/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "1.1.0"
1+
__version__ = "1.1.1"
22
AUTHOR = 'Vanessa Sochat'
33
AUTHOR_EMAIL = '[email protected]'
44
NAME = 'singularity'

singularity/views/trees.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
singularity views/trees.py: part of singularity package
55
66
'''
7-
7+
from functools import reduce
88
import json
99

1010
from singularity.logman import bot
@@ -227,3 +227,63 @@ def make_package_tree(matrix=None,labels=None,width=25,height=10,title=None):
227227
leaf_font_size=8., # font size for the x axis labels
228228
labels=labels)
229229
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

Comments
 (0)