/
20110427a.py
121 lines (110 loc) · 4.02 KB
/
20110427a.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
Compute Perron values near a vertex of a tree.
Given a single specified vertex of articulation,
all other vertices of articulation in a given tree
are removed by Schur complementation.
Let L~ be the resulting Laplacian matrix relating the p+1 remaining
vertices where p is the number of leaves of the original tree.
If the specified vertex of articulation has degree d then
the vertices can be partitioned into d+1 sets
where C0 has only the specified vertex
and Ci has the original leaves, for 1<=i<=d.
The spectral norms of inverses of principal submatrices of L~
corresponding to C1, ..., Cd are the Perron values.
In other words, the Perron values are the spectral norms
of the bottleneck matrices corresponding to C1, ..., Cd.
"""
from StringIO import StringIO
from collections import defaultdict
import scipy
import Form
import FormOut
import Harmonic
import Ftree
import FtreeIO
import Newick
g_default_tree = '(((3:0.333333333333, 4:0.5)7:1.0, 5:1.0)8:0.088383145868, (1:1.0, 2:0.5)6:0.911616854132)r;'
def get_form():
"""
@return: the body of a form
"""
# format the default tree string
tree = Newick.parse(g_default_tree, Newick.NewickTree)
formatted_tree_string = Newick.get_narrow_newick_string(tree, 60)
# define the form objects
form_objects = [
Form.MultiLine('tree', 'tree', formatted_tree_string),
Form.SingleLine('vertex',
'distinguished vertex of articulation', 'r')]
return form_objects
def get_form_out():
return FormOut.Report()
def get_unique_vertex(N, name):
"""
@param N: vertex to name
"""
if len(set(N.values())) != len(N.values()):
raise ValueError('vertex names should be unique')
name_to_v = dict((n, v) for v, n in N.items())
if name not in name_to_v:
raise ValueError('the vertex name was not found in the newick string')
return name_to_v[name]
def get_algebraic_connectivity(T, B, leaves):
L_schur = Ftree.TB_to_L_schur(T, B, leaves)
w = scipy.linalg.eigh(L_schur, eigvals_only=True)
return w[1]
def get_response_content(fs):
# read the tree
T, B, N = FtreeIO.newick_to_TBN(fs.tree)
leaves = Ftree.T_to_leaves(T)
internal = Ftree.T_to_internal_vertices(T)
# get the distinguished vertex of articulation
r = get_unique_vertex(N, fs.vertex)
if r not in internal:
raise ValueError(
'the distinguished vertex should have degree at least two')
# Partition the leaves with respect to the given root.
# Each set of leaves will eventually define a connected component.
R = Ftree.T_to_R_specific(T, r)
v_to_sinks = Ftree.R_to_v_to_sinks(R)
# break some edges
R_pruned = set(R)
neighbors = Ftree.T_to_v_to_neighbors(T)[r]
for adj in neighbors:
R_pruned.remove((r, adj))
T_pruned = Ftree.R_to_T(R_pruned)
# get the leaf partition
ordered_leaves = []
leaf_lists = []
for adj in neighbors:
R_subtree = Ftree.T_to_R_specific(T_pruned, adj)
C = sorted(b for a, b in R_subtree if b not in v_to_sinks)
ordered_leaves.extend(C)
leaf_lists.append(C)
# define the vertices to keep and those to remove
keepers = ordered_leaves + [r]
# get the schur complement
L_schur = Ftree.TB_to_L_schur(T, B, keepers)
# get principal submatrices of the schur complement
principal_matrices = []
accum = 0
for component_leaves in leaf_lists:
n = len(component_leaves)
M = L_schur[accum:accum+n, accum:accum+n]
principal_matrices.append(M)
accum += n
# write the report
out = StringIO()
print >> out, 'algebraic connectivity:'
print >> out, get_algebraic_connectivity(T, B, leaves)
print >> out
print >> out
print >> out, 'perron values:'
print >> out
for M, leaf_list in zip(principal_matrices, leaf_lists):
value = scipy.linalg.eigh(M, eigvals_only=True)[0]
name_list = [N[v] for v in leaf_list]
print >> out, name_list
print >> out, value
print >> out
return out.getvalue()