def get_response_content(fs): nseconds_limit = 5.0 R_true, B_true = FtreeIO.newick_to_RB(fs.true_tree, int) R_test = FtreeIO.newick_to_R(fs.test_tree, int) # get the unrooted tree topology T_true = Ftree.R_to_T(R_true) T_test = Ftree.R_to_T(R_test) # check the trees for vertex compatibility if set(Ftree.T_to_order(T_true)) != set(Ftree.T_to_order(T_test)): raise ValueError('vertex sets are not equal') if set(Ftree.T_to_leaves(T_true)) != set(Ftree.T_to_leaves(T_test)): raise ValueError('leaf vertex sets are not equal') if set(Ftree.T_to_internal_vertices(T_true)) != set( Ftree.T_to_internal_vertices(T_test)): raise ValueError('internal vertex sets are not equal') # get the 2D MDS for the true tree leaves = Ftree.T_to_leaves(T_true) internal = Ftree.T_to_internal_vertices(T_true) vertices = leaves + internal L_schur = Ftree.TB_to_L_schur(T_true, B_true, leaves) w_all, Vp_all = scipy.linalg.eigh(L_schur) w, Vp = w_all[1:3], Vp_all[:, 1:3] # make the constant matrix for Frobenius norm comparison C = np.zeros((len(vertices), 2)) C[:len(leaves)] = w*Vp # keep doing iterations until we run out of time mymax = 256 t_initial = time.time() while time.time() - t_initial < nseconds_limit / 2: mymax *= 2 f = Functor(T_test.copy(), Vp.copy(), C.copy(), w.copy()) initial_guess = np.ones(len(T_test) + 2*len(internal)) results = scipy.optimize.fmin( f, initial_guess, ftol=1e-8, xtol=1e-8, full_output=True, maxfun=mymax, maxiter=mymax) xopt, fopt, itr, funcalls, warnflag = results # look at the values from the longest running iteration B, Vr = f.X_to_B_Vr(xopt) L, V = f.X_to_L_V(xopt) Lrr = Ftree.TB_to_L_block(T_test, B, internal, internal) Lrp = Ftree.TB_to_L_block(T_test, B, internal, leaves) H_ext = -np.dot(np.linalg.pinv(Lrr), Lrp) N = dict((v, str(v)) for v in vertices) # start writing the response out = StringIO() print >> out, 'xopt:', xopt print >> out, 'fopt:', fopt print >> out, 'number of iterations:', itr print >> out, 'number of function calls:', funcalls print >> out, 'warning flags:', warnflag print >> out, 'first four eigenvalues:', w_all[:4] print >> out, 'Vr:' print >> out, Vr print >> out, '-Lrr^-1 Lrp Vp:' print >> out, np.dot(H_ext, Vp) print >> out, C print >> out, np.dot(L, V) print >> out, FtreeIO.RBN_to_newick(R_test, B, N) return out.getvalue()
def get_response_content(fs): # read the trees T_true, B_true, N_true = FtreeIO.newick_to_TBN(fs.true_tree) T_test, B_test, N_test = FtreeIO.newick_to_TBN(fs.test_tree) # we are concerned about the names of the leaves of the two trees true_leaves = Ftree.T_to_leaves(T_true) test_leaves = Ftree.T_to_leaves(T_test) true_leaf_to_n = dict((v, N_true[v]) for v in true_leaves) test_leaf_to_n = dict((v, N_test[v]) for v in test_leaves) # check that all leaves are named if len(true_leaves) != len(true_leaf_to_n): raise ValueError( 'all leaves in the leaf MDS tree should be named') if len(test_leaves) != len(test_leaf_to_n): raise ValueError( 'all leaves in the harmonic extension tree should be named') # check that within each tree all leaves are uniquely named if len(set(true_leaf_to_n.values())) != len(true_leaves): raise ValueError( 'all leaf names in the leaf MDS tree should be unique') if len(set(test_leaf_to_n.values())) != len(test_leaves): raise ValueError( 'all leaf names in the harmonic extension tree ' 'should be unique') # check that the leaf name sets are the same if set(true_leaf_to_n.values()) != set(test_leaf_to_n.values()): raise ValueError( 'the two trees should have corresponding leaf names') # invert the leaf name maps true_n_to_leaf = dict((n, v) for v, n in true_leaf_to_n.items()) test_n_to_leaf = dict((n, v) for v, n in test_leaf_to_n.items()) # get correspondingly ordered leaf sequences leaf_names = true_leaf_to_n.values() true_leaves_reordered = [true_n_to_leaf[n] for n in leaf_names] test_leaves_reordered = [test_n_to_leaf[n] for n in leaf_names] # get the Schur complement matrix for the leaves L_schur_true = Ftree.TB_to_L_schur(T_true, B_true, true_leaves_reordered) # get the MDS points w, V = scipy.linalg.eigh(L_schur_true, eigvals=(1, 2)) X = np.dot(V, np.diag(np.reciprocal(np.sqrt(w)))) # get the linear operator that defines the harmonic extension test_internal = Ftree.T_to_internal_vertices(T_test) L22 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_internal) L21 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_leaves_reordered) M = -np.dot(np.linalg.pinv(L22), L21) # get the harmonic extension X_extension = np.dot(M, X) X_extended = np.vstack([X, X_extension]) # draw the image v_to_index = Ftree.invseq(test_leaves_reordered + test_internal) physical_size = (640, 480) ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T_test, X_extended)
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 valuations with harmonic extensions w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) # get the Fiedler valuations with harmonic extensions h = V[:, 0] # check for vertices with small valuations eps = 1e-8 if any(abs(x) < x for x in h): raise ValueError('the tree has no clear harmonic Fiedler point') # find the edge contining the harmonic Fiedler point v_to_val = dict((v, h[i]) for i, v in enumerate(leaves + internal)) d_edges = [(a, b) for a, b in T if v_to_val[a] * v_to_val[b] < 0] if len(d_edges) != 1: raise ValueError('expected the point to fall clearly on a single edge') d_edge = d_edges[0] a, b = d_edge # find the proportion along the directed edge t = v_to_val[a] / (v_to_val[a] - v_to_val[b]) # find the distance from the new root to each endpoint vertices u_edge = frozenset(d_edge) d = B[u_edge] da = t * d db = (1 - t) * d # create the new tree r = max(Ftree.T_to_order(T)) + 1 N[r] = fs.root_name T.remove(u_edge) del B[u_edge] ea = frozenset((r, a)) eb = frozenset((r, b)) T.add(ea) T.add(eb) B[ea] = da B[eb] = db # add a new leaf with arbitrary branch length leaf = r + 1 N[leaf] = fs.leaf_name u_edge = frozenset((r, leaf)) T.add(u_edge) B[u_edge] = 1.0 # get the best branch length to cause eigenvalue multiplicity blen = scipy.optimize.golden(get_gap, (T, B, u_edge), full_output=False, tol=1e-12) B[u_edge] = blen # return the string representation of the new tree R = Ftree.T_to_R_specific(T, r) return FtreeIO.RBN_to_newick(R, B, N)
def get_tikz_lines(newick, eigenvector_index, yaw, pitch): """ @param eigenvector_index: 1 is Fiedler """ tree = Newick.parse(newick, SpatialTree.SpatialTree) # change the node names and get the new tree string for node in tree.preorder(): node.name = 'n' + str(id(node)) newick = NewickIO.get_newick_string(tree) # do the layout layout = FastDaylightLayout.StraightBranchLayout() layout.do_layout(tree) tree.fit((g_xy_scale, g_xy_scale)) name_to_location = dict(( x.name, tree._layout_to_display(x.location)) for x in tree.preorder()) T, B, N = FtreeIO.newick_to_TBN(newick) # get some vertices leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # get the locations v_to_location = dict((v, name_to_location[N[v]]) for v in vertices) # get the valuations w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) index_to_val = V[:, eigenvector_index-1] v_to_val = dict( (vertices[i], g_z_scale*val) for i, val in enumerate(index_to_val)) # get the coordinates v_to_xyz = get_v_to_xyz(yaw, v_to_location, v_to_val) # add intersection vertices add_intersection_vertices(T, B, v_to_xyz) intersection_vertices = sorted(v for v in v_to_xyz if v not in vertices) # get lines of the tikz file return xyz_to_tikz_lines(T, B, pitch, v_to_xyz, leaves, internal, intersection_vertices)
def get_response_content(fs): """ @param fs: a FieldStorage object containing the cgi arguments @return: the response """ # get a properly formatted newick tree with branch lengths T, B, N = FtreeIO.newick_to_TBN(fs.tree) # get the vertex valuations all_valuations = TB_to_harmonic_valuations(T, B) valuations = all_valuations[fs.first_index:] nfigures = (fs.last_index - fs.first_index) + 1 # do the layout if fs.equal_arc_layout: v_to_location = FtreeAux.equal_arc_layout(T, B) elif fs.equal_daylight_layout: v_to_location = FtreeAux.equal_daylight_layout(T, B, 3) # draw the image physical_size = (fs.width, fs.height) tikzpicture = DrawEigenLacing.get_forest_image_ftree( T, B, N, v_to_location, physical_size, valuations, nfigures, fs.inner_margin, fs.reflect_trees, fs.show_vertex_labels, fs.show_subfigure_labels) packages = [] preamble = '\\usetikzlibrary{snakes}' return tikz.get_figure_response( tikzpicture, fs.tikzformat, g_figure_caption, g_figure_label, packages, preamble)
def get_tikz_lines(newick, eigenvector_index, yaw, pitch): """ @param eigenvector_index: 1 is Fiedler """ tree = Newick.parse(newick, SpatialTree.SpatialTree) # change the node names and get the new tree string for node in tree.preorder(): node.name = 'n' + str(id(node)) newick = NewickIO.get_newick_string(tree) # do the layout layout = FastDaylightLayout.StraightBranchLayout() layout.do_layout(tree) tree.fit((g_xy_scale, g_xy_scale)) name_to_location = dict( (x.name, tree._layout_to_display(x.location)) for x in tree.preorder()) T, B, N = FtreeIO.newick_to_TBN(newick) # get some vertices leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # get the locations v_to_location = dict((v, name_to_location[N[v]]) for v in vertices) # get the valuations w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) index_to_val = V[:, eigenvector_index - 1] v_to_val = dict( (vertices[i], g_z_scale * val) for i, val in enumerate(index_to_val)) # get the coordinates v_to_xyz = get_v_to_xyz(yaw, v_to_location, v_to_val) # add intersection vertices add_intersection_vertices(T, B, v_to_xyz) intersection_vertices = sorted(v for v in v_to_xyz if v not in vertices) # get lines of the tikz file return xyz_to_tikz_lines(T, B, pitch, v_to_xyz, leaves, internal, intersection_vertices)
def get_response_content(fs): # define the requested physical size of the images (in pixels) physical_size = (640, 480) # get the directed edges and the branch lengths and vertex names R, B, N = FtreeIO.newick_to_RBN(fs.tree_string) # get the requested undirected edge edge = get_edge(R, N, fs.branch_name) # get the undirected tree topology T = Ftree.R_to_T(R) # get the leaves and the vertices of articulation leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) v_to_index = Ftree.invseq(vertices) # get the requested indices x_index = fs.x_axis - 1 y_index = fs.y_axis - 1 if x_index >= nleaves-1 or y_index >= nleaves-1: raise ValueError( 'projection indices must be smaller than the number of leaves') # adjust the branch length initial_length = B[edge] t = sigmoid(fs.frame_progress) B[edge] = (1-t)*initial_length + t*fs.final_length # get the points w, v = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) X_full = np.dot(v, np.diag(np.reciprocal(np.sqrt(w)))) X = np.vstack([X_full[:,x_index], X_full[:,y_index]]).T # draw the image ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T, X, w)
def get_response_content(fs): # define the requested physical size of the images (in pixels) physical_size = (640, 480) # get the directed edges and the branch lengths and vertex names R, B, N = FtreeIO.newick_to_RBN(fs.tree_string) # get the requested undirected edge edge = get_edge(R, N, fs.branch_name) # get the undirected tree topology T = Ftree.R_to_T(R) # get the leaves and the vertices of articulation leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) v_to_index = Ftree.invseq(vertices) # get the requested indices x_index = fs.x_axis - 1 y_index = fs.y_axis - 1 if x_index >= nleaves - 1 or y_index >= nleaves - 1: raise ValueError( 'projection indices must be smaller than the number of leaves') # adjust the branch length initial_length = B[edge] t = sigmoid(fs.frame_progress) B[edge] = (1 - t) * initial_length + t * fs.final_length # get the points w, v = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) X_full = np.dot(v, np.diag(np.reciprocal(np.sqrt(w)))) X = np.vstack([X_full[:, x_index], X_full[:, y_index]]).T # draw the image ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T, X, w)
def get_response_content(fs): """ @param fs: a FieldStorage object containing the cgi arguments @return: the response """ # get a properly formatted newick tree with branch lengths T, B, N = FtreeIO.newick_to_TBN(fs.tree) # get the vertex valuations reflect = False all_valuations = TB_to_harmonic_valuations(T, B, reflect) fiedler_valuations = all_valuations[1] # do the layout v_to_location = FtreeAux.equal_daylight_layout(T, B, 3) # get the vertex list and the initial vertex locations vertices = Ftree.T_to_leaves(T) + Ftree.T_to_internal_vertices(T) X_in = np.array([tuple(v_to_location[v]) for v in vertices]) # fit the tree to the physical size physical_size = (fs.width, fs.height) theta = layout.get_best_angle(X_in, physical_size) X = layout.rotate_2d_centroid(X_in, theta) sz = layout.get_axis_aligned_size(X) sf = layout.get_scaling_factor(sz, physical_size) X *= sf # get the map from id to location for the final tree layout v_to_location = dict((v, tuple(r)) for v, r in zip(vertices, X)) # draw the image context = TikzContext() draw_plain_branches_ftree(T, B, context, v_to_location) draw_ticks_ftree(T, B, context, fiedler_valuations, v_to_location) draw_labels_ftree(T, N, context, v_to_location) context.finish() # get the response tikzpicture = context.get_text() return tikz.get_response(tikzpicture, fs.tikzformat)
def __call__(self, X_logs): """ The vth entry of X corresponds to the log rate of the branch above v. Return the quantity to be minimized (the neg log likelihood). @param X: vector of branch rate logs @return: negative log likelihood """ X = [math.exp(x) for x in X_logs] B_subs = {} for v_parent, v_child in self.R: edge = frozenset([v_parent, v_child]) r = X[v_child] t = self.B[edge] B_subs[edge] = r * t newick_string = FtreeIO.RBN_to_newick(self.R, B_subs, self.N_leaves) tree = Newick.parse(newick_string, Newick.NewickTree) # define the rate matrix object; horrible dictionary_rate_matrix = RateMatrix.get_jukes_cantor_rate_matrix() ordered_states = list('ACGT') row_major_rate_matrix = MatrixUtil.dict_to_row_major( dictionary_rate_matrix, ordered_states, ordered_states) rate_matrix_object = RateMatrix.RateMatrix( row_major_rate_matrix, ordered_states) # get the log likelihood ll = PhyLikelihood.get_log_likelihood( tree, self.alignment, rate_matrix_object) return -ll
def test_leaf_distn_a(self): # Read the example tree. example_tree = '(a:2, (b:1, c:1, d:1, e:1)x:1)y;' R, B, N = FtreeIO.newick_to_RBN(example_tree) T = Ftree.R_to_T(R) r = Ftree.R_to_root(R) # Get the leaf distribution associated with the root. internal_to_leaf_distn = get_internal_vertex_to_leaf_distn(T, B) r_to_leaf_distn = internal_to_leaf_distn[r] leaves = Ftree.T_to_leaves(T) observed_name_weight_pairs = [ (N[v], r_to_leaf_distn[v]) for v in leaves] # Set up the expectation for the test. n = 5.0 expected_name_weight_pairs = [] expected_first_value = n / (3*n - 2) expected_non_first_value = 2 / (3*n - 2) expected_name_weight_pairs.append(('a', expected_first_value)) for name in list('bcde'): expected_name_weight_pairs.append((name, expected_non_first_value)) # Do the comparison for testing. expected_d = dict(expected_name_weight_pairs) observed_d = dict(observed_name_weight_pairs) for v in leaves: name = N[v] expected_value = expected_d[name] observed_value = observed_d[name] self.assertTrue(np.allclose(expected_value, observed_value))
def get_response_content(fs): # read the trees T_true, B_true, N_true = FtreeIO.newick_to_TBN(fs.true_tree) T_test, B_test, N_test = FtreeIO.newick_to_TBN(fs.test_tree) # we are concerned about the names of the leaves of the two trees true_leaves = Ftree.T_to_leaves(T_true) test_leaves = Ftree.T_to_leaves(T_test) true_leaf_to_n = dict((v, N_true[v]) for v in true_leaves) test_leaf_to_n = dict((v, N_test[v]) for v in test_leaves) # check that all leaves are named if len(true_leaves) != len(true_leaf_to_n): raise ValueError("all leaves in the leaf MDS tree should be named") if len(test_leaves) != len(test_leaf_to_n): raise ValueError("all leaves in the harmonic extension tree should be named") # check that within each tree all leaves are uniquely named if len(set(true_leaf_to_n.values())) != len(true_leaves): raise ValueError("all leaf names in the leaf MDS tree should be unique") if len(set(test_leaf_to_n.values())) != len(test_leaves): raise ValueError("all leaf names in the harmonic extension tree " "should be unique") # check that the leaf name sets are the same if set(true_leaf_to_n.values()) != set(test_leaf_to_n.values()): raise ValueError("the two trees should have corresponding leaf names") # invert the leaf name maps true_n_to_leaf = dict((n, v) for v, n in true_leaf_to_n.items()) test_n_to_leaf = dict((n, v) for v, n in test_leaf_to_n.items()) # get correspondingly ordered leaf sequences leaf_names = true_leaf_to_n.values() true_leaves_reordered = [true_n_to_leaf[n] for n in leaf_names] test_leaves_reordered = [test_n_to_leaf[n] for n in leaf_names] # get the Schur complement matrix for the leaves L_schur_true = Ftree.TB_to_L_schur(T_true, B_true, true_leaves_reordered) # get the MDS points w, V = scipy.linalg.eigh(L_schur_true, eigvals=(1, 2)) X = np.dot(V, np.diag(np.reciprocal(np.sqrt(w)))) # get the linear operator that defines the harmonic extension test_internal = Ftree.T_to_internal_vertices(T_test) L22 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_internal) L21 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_leaves_reordered) M = -np.dot(np.linalg.pinv(L22), L21) # get the harmonic extension X_extension = np.dot(M, X) X_extended = np.vstack([X, X_extension]) # draw the image v_to_index = Ftree.invseq(test_leaves_reordered + test_internal) physical_size = (640, 480) ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T_test, X_extended)
def get_starting_tree_defn(R, B, N_leaves): """ """ out = StringIO() N_aug = dict((v, 'taxon_' + name) for v, name in N_leaves.items()) print >> out, '<newick id="startingTree">' print >> out, FtreeIO.RBN_to_newick(R, B, N_aug) print >> out, '</newick>' return out.getvalue().rstrip()
def __init__(self): self.tree_string = Newick.daylight_example_tree T, B, N = FtreeIO.newick_to_TBN(self.tree_string) self.T = T self.B = B self.v_to_name = N self.v_to_point = self._get_v_to_point() self.v_to_layout_point = self._get_v_to_layout_point() self.shape = self.get_shape()
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()
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 valuations with harmonic extensions w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) # get the Fiedler valuations with harmonic extensions h = V[:, 0] # check for vertices with small valuations eps = 1e-8 if any(abs(x) < x for x in h): raise ValueError('the tree has no clear harmonic Fiedler point') # find the edge contining the harmonic Fiedler point v_to_val = dict((v, h[i]) for i, v in enumerate(leaves + internal)) d_edges = [(a, b) for a, b in T if v_to_val[a] * v_to_val[b] < 0] if len(d_edges) != 1: raise ValueError('expected the point to fall clearly on a single edge') d_edge = d_edges[0] a, b = d_edge # find the proportion along the directed edge t = v_to_val[a] / (v_to_val[a] - v_to_val[b]) # find the distance from the new root to each endpoint vertices u_edge = frozenset(d_edge) d = B[u_edge] da = t * d db = (1 - t) * d # create the new tree r = max(Ftree.T_to_order(T)) + 1 T.remove(u_edge) del B[u_edge] ea = frozenset((r, a)) eb = frozenset((r, b)) T.add(ea) T.add(eb) B[ea] = da B[eb] = db R = Ftree.T_to_R_specific(T, r) # return the string representation of the new tree return FtreeIO.RBN_to_newick(R, B, N)
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 valuations with harmonic extensions w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) # get the Fiedler valuations with harmonic extensions h = V[:,0] # check for vertices with small valuations eps = 1e-8 if any(abs(x)<x for x in h): raise ValueError('the tree has no clear harmonic Fiedler point') # find the edge contining the harmonic Fiedler point v_to_val = dict((v, h[i]) for i, v in enumerate(leaves + internal)) d_edges = [(a,b) for a, b in T if v_to_val[a]*v_to_val[b] < 0] if len(d_edges) != 1: raise ValueError('expected the point to fall clearly on a single edge') d_edge = d_edges[0] a, b = d_edge # find the proportion along the directed edge t = v_to_val[a] / (v_to_val[a] - v_to_val[b]) # find the distance from the new root to each endpoint vertices u_edge = frozenset(d_edge) d = B[u_edge] da = t*d db = (1-t)*d # create the new tree r = max(Ftree.T_to_order(T)) + 1 N[r] = fs.root_name T.remove(u_edge) del B[u_edge] ea = frozenset((r, a)) eb = frozenset((r, b)) T.add(ea) T.add(eb) B[ea] = da B[eb] = db # add a new leaf with arbitrary branch length leaf = r + 1 N[leaf] = fs.leaf_name u_edge = frozenset((r, leaf)) T.add(u_edge) B[u_edge] = 1.0 # get the best branch length to cause eigenvalue multiplicity blen = scipy.optimize.golden( get_gap, (T, B, u_edge), full_output=False, tol=1e-12) B[u_edge] = blen # return the string representation of the new tree R = Ftree.T_to_R_specific(T, r) return FtreeIO.RBN_to_newick(R, B, N)
def get_response_content(fs): # read the ordered leaf names for the distance matrix D_names = Util.get_stripped_lines(fs.names.splitlines()) # read the tree T_test, B_test, N_test = FtreeIO.newick_to_TBN(fs.test_tree) # we are concerned about the names of the leaves of the two trees test_leaves = Ftree.T_to_leaves(T_test) test_leaf_to_n = dict((v, N_test[v]) for v in test_leaves) # check that all leaves are named if len(D_names) != len(fs.D): raise HandlingError( 'the number of ordered leaf names ' 'should be the same as the number of rows ' 'in the distance matrix') if len(test_leaves) != len(test_leaf_to_n): raise ValueError( 'all leaves in the harmonic extension tree ' 'should be named') # check that leaves are uniquely named if len(set(D_names)) != len(D_names): raise ValueError( 'all ordered leaf names in the distance matrix ' 'should be unique') # check that the leaf name sets are the same if set(D_names) != set(test_leaf_to_n.values()): raise ValueError( 'the set of leaf names on the tree ' 'should be the same as ' 'the set of leaf names for the distance matrix') # invert the leaf name map test_n_to_leaf = dict((n, v) for v, n in test_leaf_to_n.items()) # get correspondingly ordered leaf sequences test_leaves_reordered = [test_n_to_leaf[n] for n in D_names] # get the MDS points X = MDS_v4(fs.D) # get the linear operator that defines the harmonic extension test_internal = Ftree.T_to_internal_vertices(T_test) L22 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_internal) L21 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_leaves_reordered) M = -np.dot(np.linalg.pinv(L22), L21) # get the harmonic extension X_extension = np.dot(M, X) X_extended = np.vstack([X, X_extension]) # draw the image v_to_index = Ftree.invseq(test_leaves_reordered + test_internal) physical_size = (640, 480) ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T_test, X_extended)
def main(args): # do some validation if args.nframes < 2: raise ValueError('nframes should be at least 2') # define the requested physical size of the images (in pixels) physical_size = (args.physical_width, args.physical_height) # get the directed edges and the branch lengths and vertex names R, B, N = FtreeIO.newick_to_RBN(args.tree) # get the requested undirected edge edge = get_edge(R, N, args.branch_name) initial_length = B[edge] # get the undirected tree topology T = Ftree.R_to_T(R) # get the leaves and the vertices of articulation leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) v_to_index = Ftree.invseq(vertices) # get the requested indices x_index = args.x_axis - 1 y_index = args.y_axis - 1 if x_index >= nleaves-1 or y_index >= nleaves-1: raise ValueError( 'projection indices must be smaller than the number of leaves') X_prev = None # create the animation frames and write them as image files pbar = Progress.Bar(args.nframes) for frame_index in range(args.nframes): linear_progress = frame_index / float(args.nframes - 1) if args.interpolation == 'sigmoid': t = sigmoid(linear_progress) else: t = linear_progress B[edge] = (1-t)*initial_length + t*args.final_length w, v = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) X_full = np.dot(v, np.diag(np.reciprocal(np.sqrt(w)))) X = np.vstack([X_full[:,x_index], X_full[:,y_index]]).T if X_prev is not None: X = reflect_to_match(X, X_prev) X_prev = X image_string = get_animation_frame( args.image_format, physical_size, args.scale, v_to_index, T, X, w) image_filename = 'frame-%04d.%s' % (frame_index, args.image_format) image_pathname = os.path.join(args.output_directory, image_filename) with open(image_pathname, 'wb') as fout: fout.write(image_string) pbar.update(frame_index+1) pbar.finish()
def main(args): # do some validation if args.nframes < 2: raise ValueError('nframes should be at least 2') # define the requested physical size of the images (in pixels) physical_size = (args.physical_width, args.physical_height) # get the directed edges and the branch lengths and vertex names R, B, N = FtreeIO.newick_to_RBN(args.tree) # get the requested undirected edge edge = get_edge(R, N, args.branch_name) initial_length = B[edge] # get the undirected tree topology T = Ftree.R_to_T(R) # get the leaves and the vertices of articulation leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) v_to_index = Ftree.invseq(vertices) # get the requested indices x_index = args.x_axis - 1 y_index = args.y_axis - 1 if x_index >= nleaves - 1 or y_index >= nleaves - 1: raise ValueError( 'projection indices must be smaller than the number of leaves') X_prev = None # create the animation frames and write them as image files pbar = Progress.Bar(args.nframes) for frame_index in range(args.nframes): linear_progress = frame_index / float(args.nframes - 1) if args.interpolation == 'sigmoid': t = sigmoid(linear_progress) else: t = linear_progress B[edge] = (1 - t) * initial_length + t * args.final_length w, v = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) X_full = np.dot(v, np.diag(np.reciprocal(np.sqrt(w)))) X = np.vstack([X_full[:, x_index], X_full[:, y_index]]).T if X_prev is not None: X = reflect_to_match(X, X_prev) X_prev = X image_string = get_animation_frame(args.image_format, physical_size, args.scale, v_to_index, T, X, w) image_filename = 'frame-%04d.%s' % (frame_index, args.image_format) image_pathname = os.path.join(args.output_directory, image_filename) with open(image_pathname, 'wb') as fout: fout.write(image_string) pbar.update(frame_index + 1) pbar.finish()
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) # root arbitrarily R = Ftree.T_to_R_canonical(T) # init some sampling parameters nsamples = 1000 npillars = 10 # Init the accumulators. # Accumulate the sum of squares of differences # and the sum of differences. # The differences are from the leaf mean. dsum = defaultdict(float) dsumsq = defaultdict(float) # Repeatedly sample using Brownian motion on the tree. for i in range(nsamples): # Sample using Brownian motion at vertices on the tree. v_to_sample = sample_brownian_motion(R, B) # Compute the mean at the leaves. mu = sum(v_to_sample[v] for v in leaves) / len(leaves) # Accumulate difference moments at vertices of the tree. for v, x in v_to_sample.items(): dsum[(v, -1, -1)] += x - mu dsumsq[(v, -1, -1)] += (x - mu)**2 # Sample using Brownian bridge on edges. for d_edge in R: u_edge = frozenset(d_edge) va, vb = d_edge a = v_to_sample[va] b = v_to_sample[vb] samples = bridge(a, b, npillars, B[u_edge]) for i, x in enumerate(samples): dsum[(va, vb, i)] += x - mu dsumsq[(va, vb, i)] += (x - mu)**2 quad = min((val, va, vb, i) for (va, vb, i), val in dsumsq.items()) val, va, vb, i = quad # write the report out = StringIO() if i < 0: print >> out, 'min sum of squares was at vertex', N[va] else: print >> out, 'min sum of squares was at edge', print >> out, N[va], '--[', i, ']-->', N[vb] print >> out print >> out, 'the min sum of squares value was', val return out.getvalue()
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) # root arbitrarily R = Ftree.T_to_R_canonical(T) # init some sampling parameters nsamples = 1000 npillars = 10 # Init the accumulators. # Accumulate the sum of squares of differences # and the sum of differences. # The differences are from the leaf mean. dsum = defaultdict(float) dsumsq = defaultdict(float) # Repeatedly sample using Brownian motion on the tree. for i in range(nsamples): # Sample using Brownian motion at vertices on the tree. v_to_sample = sample_brownian_motion(R, B) # Compute the mean at the leaves. mu = sum(v_to_sample[v] for v in leaves) / len(leaves) # Accumulate difference moments at vertices of the tree. for v, x in v_to_sample.items(): dsum[(v, -1, -1)] += x-mu dsumsq[(v, -1, -1)] += (x-mu)**2 # Sample using Brownian bridge on edges. for d_edge in R: u_edge = frozenset(d_edge) va, vb = d_edge a = v_to_sample[va] b = v_to_sample[vb] samples = bridge(a, b, npillars, B[u_edge]) for i, x in enumerate(samples): dsum[(va, vb, i)] += x-mu dsumsq[(va, vb, i)] += (x-mu)**2 quad = min((val, va, vb, i) for (va, vb, i), val in dsumsq.items()) val, va, vb, i = quad # write the report out = StringIO() if i < 0: print >> out, 'min sum of squares was at vertex', N[va] else: print >> out, 'min sum of squares was at edge', print >> out, N[va], '--[', i, ']-->', N[vb] print >> out print >> out, 'the min sum of squares value was', val return out.getvalue()
def get_response_content(fs): """ @param fs: a FieldStorage object containing the cgi arguments @return: the response """ T, B, N = FtreeIO.newick_to_TBN(fs.tree_string) # sanitize taxon labels if requested if fs.sanitization: for v in N: N[v] = latexutil.sanitize(N[v]) # scale branch lengths so the diameter is 1 diameter = np.max(Ftree.TB_to_D(T, B, Ftree.T_to_leaves(T))) # scale the branch lengths for u_edge in T: B[u_edge] /= diameter info = FigureInfo(T, B, N, fs.label_mode) # get the texts tikz_bodies = [ info.get_tikz_tree(fs.tree_layout), info.get_tikz_MDS_full(), info.get_tikz_MDS_partial(), info.get_tikz_MDS_harmonic(), ] tikz_pictures = [] for b in tikz_bodies: tikzpicture = tikz.get_picture(b, 'auto', scale=fs.scaling_factor) tikz_pictures.append(tikzpicture) figure_body = '\n'.join([ '\\subfloat[]{', tikz_pictures[0], '}', '\\subfloat[]{', tikz_pictures[1], '} \\\\', '\\subfloat[]{', tikz_pictures[2], '}', '\\subfloat[]{', tikz_pictures[3], '}', ]) packages = ['tikz', 'subfig'] preamble = '' figure_caption = None figure_label = None return latexutil.get_centered_figure_response( figure_body, fs.latexformat, figure_caption, figure_label, packages, preamble)
def get_response_content(fs): # read the ordered leaf names for the distance matrix D_names = Util.get_stripped_lines(fs.names.splitlines()) # read the tree T_test, B_test, N_test = FtreeIO.newick_to_TBN(fs.test_tree) # we are concerned about the names of the leaves of the two trees test_leaves = Ftree.T_to_leaves(T_test) test_leaf_to_n = dict((v, N_test[v]) for v in test_leaves) # check that all leaves are named if len(D_names) != len(fs.D): raise HandlingError('the number of ordered leaf names ' 'should be the same as the number of rows ' 'in the distance matrix') if len(test_leaves) != len(test_leaf_to_n): raise ValueError('all leaves in the harmonic extension tree ' 'should be named') # check that leaves are uniquely named if len(set(D_names)) != len(D_names): raise ValueError('all ordered leaf names in the distance matrix ' 'should be unique') # check that the leaf name sets are the same if set(D_names) != set(test_leaf_to_n.values()): raise ValueError('the set of leaf names on the tree ' 'should be the same as ' 'the set of leaf names for the distance matrix') # invert the leaf name map test_n_to_leaf = dict((n, v) for v, n in test_leaf_to_n.items()) # get correspondingly ordered leaf sequences test_leaves_reordered = [test_n_to_leaf[n] for n in D_names] # get the MDS points X = MDS_v4(fs.D) # get the linear operator that defines the harmonic extension test_internal = Ftree.T_to_internal_vertices(T_test) L22 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_internal) L21 = Ftree.TB_to_L_block(T_test, B_test, test_internal, test_leaves_reordered) M = -np.dot(np.linalg.pinv(L22), L21) # get the harmonic extension X_extension = np.dot(M, X) X_extended = np.vstack([X, X_extension]) # draw the image v_to_index = Ftree.invseq(test_leaves_reordered + test_internal) physical_size = (640, 480) ext = Form.g_imageformat_to_ext[fs.imageformat] return get_animation_frame(ext, physical_size, fs.scale, v_to_index, T_test, X_extended)
def test_leaf_distn_schur(self): # Read the example tree. example_tree = LeafWeights.g_acl_tree R, B, N = FtreeIO.newick_to_RBN(example_tree) T = Ftree.R_to_T(R) r = Ftree.R_to_root(R) # Get the leaf distribution associated with the root. leaf_distn = get_leaf_distn_schur(R, B) leaves = Ftree.T_to_leaves(T) observed_name_weight_pairs = [ (N[v], leaf_distn[v]) for v in leaves] # Do the comparison for testing. observed_name_to_weight = dict(observed_name_weight_pairs) for name in LeafWeights.g_acl_ordered_names: s_expected = LeafWeights.g_acl_expected_weights[name] s_observed = '%.3f' % observed_name_to_weight[name] self.assertEqual(s_expected, s_observed)
def get_tikz_lines(fs): """ @param fs: user input @return: a sequence of tikz lines """ newick = fs.tree_string # hardcode the axes x_index = 0 y_index = 1 # get the tree with ordered vertices #T, B = FtreeIO.newick_to_TB(newick, int) T, B, N = FtreeIO.newick_to_TBN(newick) leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # get the harmonic extension points w, v = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) # possibly scale using the eigenvalues if fs.scale_using_eigenvalues: X_full = np.dot(v, np.diag(np.reciprocal(np.sqrt(w)))) else: X_full = v # scale using the scaling factor X_full *= fs.scaling_factor # get the first two axes X = np.vstack([X_full[:,x_index], X_full[:,y_index]]).T # get the tikz lines axis_lines = [ '% draw the axes', '\\node (axisleft) at (0, -5) {};', '\\node (axisright) at (0, 5) {};', '\\node (axistop) at (5, 0) {};', '\\node (axisbottom) at (-5, 0) {};', '\\path (axisleft) edge[draw,color=lightgray] node {} (axisright);', '\\path (axistop) edge[draw,color=lightgray] node {} (axisbottom);'] node_lines = [] for v, (x,y) in zip(vertices, X.tolist()): line = get_vertex_line(v, x, y) node_lines.append(line) edge_lines = [] for va, vb in T: line = get_edge_line(va, vb) edge_lines.append(line) return axis_lines + node_lines + edge_lines
def get_tikz_lines(newick): tree = Newick.parse(newick, SpatialTree.SpatialTree) # layout = FastDaylightLayout.StraightBranchLayout() # layout.set_iteration_count(20) # layout.do_layout(tree) EqualArcLayout.do_layout(tree) tree.fit((2.0, 2.0)) name_to_location = dict((x.name, tree._layout_to_display(x.location)) for x in tree.preorder()) T, B, N = FtreeIO.newick_to_TBN(newick) node_lines = [] for v, depth in Ftree.T_to_v_to_centrality(T).items(): x, y = name_to_location[N[v]] line = get_vertex_line(v, depth, x, y) node_lines.append(line) edge_lines = [] for va, vb in T: line = get_edge_line(va, vb) edge_lines.append(line) return node_lines + edge_lines
def get_tikz_lines(newick): tree = Newick.parse(newick, SpatialTree.SpatialTree) #layout = FastDaylightLayout.StraightBranchLayout() #layout.set_iteration_count(20) #layout.do_layout(tree) EqualArcLayout.do_layout(tree) tree.fit((2.0, 2.0)) name_to_location = dict( (x.name, tree._layout_to_display(x.location)) for x in tree.preorder()) T, B, N = FtreeIO.newick_to_TBN(newick) node_lines = [] for v, depth in Ftree.T_to_v_to_centrality(T).items(): x, y = name_to_location[N[v]] line = get_vertex_line(v, depth, x, y) node_lines.append(line) edge_lines = [] for va, vb in T: line = get_edge_line(va, vb) edge_lines.append(line) return node_lines + edge_lines
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 valuations with harmonic extensions w, V = Ftree.TB_to_harmonic_extension(T, B, leaves, internal) # get the Fiedler valuations with harmonic extensions h = V[:,0] # check for vertices with small valuations eps = 1e-8 if any(abs(x)<x for x in h): raise ValueError('the tree has no clear harmonic Fiedler point') # find the edge contining the harmonic Fiedler point v_to_val = dict((v, h[i]) for i, v in enumerate(leaves + internal)) d_edges = [(a,b) for a, b in T if v_to_val[a]*v_to_val[b] < 0] if len(d_edges) != 1: raise ValueError('expected the point to fall clearly on a single edge') d_edge = d_edges[0] a, b = d_edge # find the proportion along the directed edge t = v_to_val[a] / (v_to_val[a] - v_to_val[b]) # find the distance from the new root to each endpoint vertices u_edge = frozenset(d_edge) d = B[u_edge] da = t*d db = (1-t)*d # create the new tree r = max(Ftree.T_to_order(T)) + 1 T.remove(u_edge) del B[u_edge] ea = frozenset((r, a)) eb = frozenset((r, b)) T.add(ea) T.add(eb) B[ea] = da B[eb] = db R = Ftree.T_to_R_specific(T, r) # return the string representation of the new tree return FtreeIO.RBN_to_newick(R, B, N)
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) # root arbitrarily R = Ftree.T_to_R_canonical(T) # init some sampling parameters npillars = 9 # init some helper variables nleaves = len(leaves) r = get_new_vertex(T) vertices = internal + [r] + leaves combo = np.array([0] * len(internal) + [1] + [-1.0 / nleaves] * nleaves) # Map edge position triple to the quadratic form value. qform = {} for d_edge in R: a, b = d_edge u_edge = frozenset(d_edge) distance = B[u_edge] for i in range(npillars): # get the proportion of the distance along the branch t = (i + 1) / float(npillars + 1) T_new, B_new = add_vertex(T, B, d_edge, r, t) # create the new centered covariance matrix L = Ftree.TB_to_L_principal(T_new, B_new, vertices) S = np.linalg.pinv(L) qform[(a, b, t * distance)] = quadratic_form(S, combo) #shortcombo = np.array([1] + [-1.0/nleaves]*nleaves) #shortvert = [r] + leaves #L_schur = Ftree.TB_to_L_schur(T_new, B_new, shortvert) #S = np.linalg.pinv(L_schur) #qform[(a, b, t*distance)] = quadratic_form(S, shortcombo) wat = sorted((val, va, vb, d) for (va, vb, d), val in qform.items()) # write the report out = StringIO() for val, va, vb, d in wat: print >> out, N[va], '--[', d, ']-->', N[vb], ':', val print >> out return out.getvalue()
def get_tikz_lines(fs): """ @param fs: user input @return: a sequence of tikz lines """ newick = fs.tree_string T, B, N = FtreeIO.newick_to_TBN(newick) # get the tree with ordered vertices leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # get the tikz lines axis_lines = [ '% draw the axes', '\\node (axisleft) at (0, -6) {};', '\\node (axisright) at (0, 6) {};', '\\node (axistop) at (6, 0) {};', '\\node (axisbottom) at (-6, 0) {};', '\\path (axisleft) edge[draw,color=lightgray] node {} (axisright);', '\\path (axistop) edge[draw,color=lightgray] node {} (axisbottom);'] # set up the figure info info = FigureInfo(T, B) # define the points caused by MDS of distance matrices with errors point_lines = [] for v_to_point in info.gen_point_samples(fs.nsamples, fs.stddev): for x, y in v_to_point.values(): line = get_point_line(fs.scaling_factor*x, fs.scaling_factor*y) point_lines.append(line) # get the tikz corresponding to the tree drawn inside the MDS plot node_lines = [] for v, (x,y) in info.get_v_to_point().items(): line = get_vertex_line(v, fs.scaling_factor*x, fs.scaling_factor*y) node_lines.append(line) edge_lines = [] for va, vb in T: line = get_edge_line(va, vb) edge_lines.append(line) # return the tikz return axis_lines + point_lines + node_lines + edge_lines
def get_response_content(fs): """ @param fs: a FieldStorage object containing the cgi arguments @return: the response """ T, B, N = FtreeIO.newick_to_TBN(fs.tree_string) leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # compute the 2D MDS of the full tree MDS_full = get_full_distance_MDS(T, B, vertices) # compute the harmonic extension of 2D MDS of the leaves MDS_harmonic = get_harmonically_extended_MDS(T, B, leaves, internal) # get the Fiedler MDS leaf partition for full 2D MDS v_to_value = dict(zip(vertices, MDS_full[:,0])) neg_leaves = frozenset([v for v in leaves if v_to_value[v] < 0]) pos_leaves = frozenset([v for v in leaves if v_to_value[v] >= 0]) full_mds_fiedler_partition = [neg_leaves, pos_leaves] # get the Fiedler MDS leaf partition for harmonic 2D MDS v_to_value = dict(zip(vertices, MDS_harmonic[:,0])) neg_leaves = frozenset([v for v in leaves if v_to_value[v] < 0]) pos_leaves = frozenset([v for v in leaves if v_to_value[v] >= 0]) harmonic_mds_fiedler_partition = [neg_leaves, pos_leaves] # get the Fiedler plus one MDS leaf partition for full 2D MDS v_to_value = dict(zip(vertices, MDS_full[:,1])) full_mds_fp1_partition = get_fp1_ordered_leaf_partition(T, v_to_value) # get the Fiedler plus one MDS leaf partition for harmonic 2D MDS v_to_value = dict(zip(vertices, MDS_harmonic[:,1])) harmonic_mds_fp1_partition = get_fp1_ordered_leaf_partition(T, v_to_value) # write the output out = StringIO() print >> out, get_2D_report( N, set(leaves), 'Full distance 2D MDS', full_mds_fiedler_partition, full_mds_fp1_partition) print >> out print >> out, get_2D_report( N, set(leaves), 'Harmonically extended 2D MDS', harmonic_mds_fiedler_partition, harmonic_mds_fp1_partition) return out.getvalue()
def get_response_content(fs): """ @param fs: a FieldStorage object containing the cgi arguments @return: the response """ T, B, N = FtreeIO.newick_to_TBN(fs.tree_string) leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # compute the 2D MDS of the full tree MDS_full = get_full_distance_MDS(T, B, vertices) # compute the harmonic extension of 2D MDS of the leaves MDS_harmonic = get_harmonically_extended_MDS(T, B, leaves, internal) # get the Fiedler MDS leaf partition for full 2D MDS v_to_value = dict(zip(vertices, MDS_full[:, 0])) neg_leaves = frozenset([v for v in leaves if v_to_value[v] < 0]) pos_leaves = frozenset([v for v in leaves if v_to_value[v] >= 0]) full_mds_fiedler_partition = [neg_leaves, pos_leaves] # get the Fiedler MDS leaf partition for harmonic 2D MDS v_to_value = dict(zip(vertices, MDS_harmonic[:, 0])) neg_leaves = frozenset([v for v in leaves if v_to_value[v] < 0]) pos_leaves = frozenset([v for v in leaves if v_to_value[v] >= 0]) harmonic_mds_fiedler_partition = [neg_leaves, pos_leaves] # get the Fiedler plus one MDS leaf partition for full 2D MDS v_to_value = dict(zip(vertices, MDS_full[:, 1])) full_mds_fp1_partition = get_fp1_ordered_leaf_partition(T, v_to_value) # get the Fiedler plus one MDS leaf partition for harmonic 2D MDS v_to_value = dict(zip(vertices, MDS_harmonic[:, 1])) harmonic_mds_fp1_partition = get_fp1_ordered_leaf_partition(T, v_to_value) # write the output out = StringIO() print >> out, get_2D_report(N, set(leaves), 'Full distance 2D MDS', full_mds_fiedler_partition, full_mds_fp1_partition) print >> out print >> out, get_2D_report(N, set(leaves), 'Harmonically extended 2D MDS', harmonic_mds_fiedler_partition, harmonic_mds_fp1_partition) return out.getvalue()
def get_tikz_lines(fs): """ @param fs: user input @return: a sequence of tikz lines """ newick = fs.tree_string T, B, N = FtreeIO.newick_to_TBN(newick) # get the tree with ordered vertices leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal # get the tikz lines axis_lines = [ '% draw the axes', '\\node (axisleft) at (0, -6) {};', '\\node (axisright) at (0, 6) {};', '\\node (axistop) at (6, 0) {};', '\\node (axisbottom) at (-6, 0) {};', '\\path (axisleft) edge[draw,color=lightgray] node {} (axisright);', '\\path (axistop) edge[draw,color=lightgray] node {} (axisbottom);' ] # set up the figure info info = FigureInfo(T, B) # define the points caused by MDS of distance matrices with errors point_lines = [] for v_to_point in info.gen_point_samples(fs.nsamples, fs.stddev): for x, y in v_to_point.values(): line = get_point_line(fs.scaling_factor * x, fs.scaling_factor * y) point_lines.append(line) # get the tikz corresponding to the tree drawn inside the MDS plot node_lines = [] for v, (x, y) in info.get_v_to_point().items(): line = get_vertex_line(v, fs.scaling_factor * x, fs.scaling_factor * y) node_lines.append(line) edge_lines = [] for va, vb in T: line = get_edge_line(va, vb) edge_lines.append(line) # return the tikz return axis_lines + point_lines + node_lines + edge_lines
def get_response_content(fs): nseconds_limit = 5.0 R_true, B_true = FtreeIO.newick_to_RB(fs.true_tree, int) R_test = FtreeIO.newick_to_R(fs.test_tree, int) # get the unrooted tree topology T_true = Ftree.R_to_T(R_true) T_test = Ftree.R_to_T(R_test) # check the trees for vertex compatibility if set(Ftree.T_to_order(T_true)) != set(Ftree.T_to_order(T_test)): raise ValueError('vertex sets are not equal') if set(Ftree.T_to_leaves(T_true)) != set(Ftree.T_to_leaves(T_test)): raise ValueError('leaf vertex sets are not equal') if set(Ftree.T_to_internal_vertices(T_true)) != set( Ftree.T_to_internal_vertices(T_test)): raise ValueError('internal vertex sets are not equal') # get the 2D MDS for the true tree leaves = Ftree.T_to_leaves(T_true) internal = Ftree.T_to_internal_vertices(T_true) vertices = leaves + internal L_schur = Ftree.TB_to_L_schur(T_true, B_true, leaves) w_all, Vp_all = scipy.linalg.eigh(L_schur) w, Vp = w_all[1:3], Vp_all[:, 1:3] # make the constant matrix for Frobenius norm comparison C = np.zeros((len(vertices), 2)) C[:len(leaves)] = w * Vp # keep doing iterations until we run out of time mymax = 256 t_initial = time.time() while time.time() - t_initial < nseconds_limit / 2: mymax *= 2 f = Functor(T_test.copy(), Vp.copy(), C.copy(), w.copy()) initial_guess = np.ones(len(T_test) + 2 * len(internal)) results = scipy.optimize.fmin(f, initial_guess, ftol=1e-8, xtol=1e-8, full_output=True, maxfun=mymax, maxiter=mymax) xopt, fopt, itr, funcalls, warnflag = results # look at the values from the longest running iteration B, Vr = f.X_to_B_Vr(xopt) L, V = f.X_to_L_V(xopt) Lrr = Ftree.TB_to_L_block(T_test, B, internal, internal) Lrp = Ftree.TB_to_L_block(T_test, B, internal, leaves) H_ext = -np.dot(np.linalg.pinv(Lrr), Lrp) N = dict((v, str(v)) for v in vertices) # start writing the response out = StringIO() print >> out, 'xopt:', xopt print >> out, 'fopt:', fopt print >> out, 'number of iterations:', itr print >> out, 'number of function calls:', funcalls print >> out, 'warning flags:', warnflag print >> out, 'first four eigenvalues:', w_all[:4] print >> out, 'Vr:' print >> out, Vr print >> out, '-Lrr^-1 Lrp Vp:' print >> out, np.dot(H_ext, Vp) print >> out, C print >> out, np.dot(L, V) print >> out, FtreeIO.RBN_to_newick(R_test, B, N) return out.getvalue()
def get_response_content(fs): # read the user input weight_delta_mu = fs.weight_delta_mu T, B, N = FtreeIO.newick_to_TBN(fs.newick) # summarize the tree leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) # define the fully connected schur complement graph as a Laplacian matrix # init the tree reconstruction state v_to_name = {} for v in leaves: name = N.get(v, None) if name is None: name = 'P' + chr(ord('a') + v) v_to_name[v] = name v_to_svs = dict((v, set([0])) for v in leaves) sv_to_vs = {0 : set(leaves)} # define edge weights (used only for spectral split strategy) G = Ftree.TB_to_L_schur(T, B, leaves) # add some random amount to each edge weight for i in range(nleaves): for j in range(i): rate = 1 / fs.weight_delta_mu x = random.expovariate(rate) G[i, j] -= x G[j, i] -= x G[i, i] += x G[j, j] += x edge_to_weight = {} for index_pair in itertools.combinations(range(nleaves), 2): i, j = index_pair leaf_pair = (leaves[i], leaves[j]) edge_to_weight[frozenset(leaf_pair)] = -G[index_pair] # define pairwise distances (used only for nj split strategy) D = Ftree.TB_to_D(T, B, leaves) edge_to_distance = {} for index_pair in itertools.combinations(range(nleaves), 2): i, j = index_pair leaf_pair = (leaves[i], leaves[j]) edge_to_distance[frozenset(leaf_pair)] = D[index_pair] # pairs like (-(number of vertices in supervertex sv), supervertex sv) active_svs = set([0]) # initialize the sources of unique vertex and supervertex identifiers v_gen = itertools.count(max(leaves)+1) sv_gen = itertools.count(1) # write the output out = StringIO() print >> out, '<html>' print >> out, '<body>' for count_pos in itertools.count(1): # add the graph rendering before the decomposition at this stage if fs.nj_split: edge_to_branch_weight = {} for k, v in edge_to_distance.items(): edge_to_branch_weight[k] = 1 / v elif fs.spectral_split: edge_to_branch_weight = edge_to_weight print >> out, '<div>' if fs.vis_star: print >> out, nhj.get_svg_star_components( active_svs, sv_to_vs, v_to_name, v_to_svs, edge_to_branch_weight) elif fs.vis_complete: print >> out, nhj.get_svg( active_svs, sv_to_vs, v_to_name, v_to_svs, edge_to_branch_weight) print >> out, '</div>' # update the splits next_active_svs = set() # svs can be decomposed independently in arbitrary order alpha_index_gen = itertools.count() for sv in active_svs: nstates = len(sv_to_vs[sv]) if nstates > 2: v_new = next(v_gen) sv_new_a = next(sv_gen) sv_new_b = next(sv_gen) alpha_index = next(alpha_index_gen) alpha = chr(ord('a') + alpha_index) v_to_name[v_new] = 'R%s%s' % (count_pos, alpha) next_active_svs.add(sv_new_a) next_active_svs.add(sv_new_b) if fs.spectral_split: if len(sv_to_vs[sv]) == 3: sv_new_c = next(sv_gen) nhj.delta_wye_transform( sv, v_to_svs, sv_to_vs, edge_to_weight, v_new, sv_new_a, sv_new_b, sv_new_c) next_active_svs.add(sv_new_c) else: nhj.harmonic_split_transform( sv, v_to_svs, sv_to_vs, edge_to_weight, v_new, sv_new_a, sv_new_b) elif fs.nj_split: sv_new_big = next(sv_gen) nhj.nj_split_transform( sv, v_to_svs, sv_to_vs, edge_to_distance, v_new, sv_new_big, sv_new_a, sv_new_b) next_active_svs.add(sv_new_big) elif nstates == 2: next_active_svs.add(sv) else: raise ValueError('supervertex has too few vertices') # if the set of active svs has not changed then we are done if active_svs == next_active_svs: break else: active_svs = next_active_svs print >> out, '</html>' print >> out, '</body>' return out.getvalue()
def get_response_content(fs): # init the response and get the user variables out = StringIO() nleaves = fs.nleaves nvertices = nleaves * 2 - 1 nbranches = nvertices - 1 nsites = fs.nsites # sample the coalescent tree with timelike branch lengths R, B = kingman.sample(fs.nleaves) r = Ftree.R_to_root(R) # get the leaf vertex names N = dict(zip(range(nleaves), string.uppercase[:nleaves])) N_leaves = dict(N) # get the internal vertex names v_to_leaves = R_to_v_to_leaves(R) for v, leaves in sorted(v_to_leaves.items()): if len(leaves) > 1: N[v] = ''.join(sorted(N[leaf] for leaf in leaves)) # get vertex ages v_to_age = kingman.RB_to_v_to_age(R, B) # sample the rates on the branches b_to_rate = sample_b_to_rate(R) xycorr = get_correlation(R, b_to_rate) # define B_subs in terms of substitutions instead of time B_subs = dict((p, t * b_to_rate[p]) for p, t in B.items()) # sample the alignment v_to_seq = sample_v_to_seq(R, B_subs, nsites) # get the log likelihood; this is kind of horrible pairs = [(N[v], ''.join(v_to_seq[v])) for v in range(nleaves)] headers, sequences = zip(*pairs) alignment = Fasta.create_alignment(headers, sequences) newick_string = FtreeIO.RBN_to_newick(R, B_subs, N_leaves) tree = Newick.parse(newick_string, Newick.NewickTree) dictionary_rate_matrix = RateMatrix.get_jukes_cantor_rate_matrix() ordered_states = list('ACGT') row_major_rate_matrix = MatrixUtil.dict_to_row_major( dictionary_rate_matrix, ordered_states, ordered_states) rate_matrix_object = RateMatrix.RateMatrix( row_major_rate_matrix, ordered_states) ll = PhyLikelihood.get_log_likelihood( tree, alignment, rate_matrix_object) # get ll when rates are all 1.0 newick_string = FtreeIO.RBN_to_newick(R, B, N_leaves) tree = Newick.parse(newick_string, Newick.NewickTree) ll_unity = PhyLikelihood.get_log_likelihood( tree, alignment, rate_matrix_object) # get ll when rates are numerically optimized # TODO incorporate the result into the xml file # TODO speed up the likelihood evaluation (beagle? C module?) #f = Opt(R, B, N_leaves, alignment) #X_logs = [0.0] * nbranches #result = scipy.optimize.fmin(f, X_logs, full_output=True) #print result # print >> out, '<?xml version="1.0"?>' print >> out, '<beast>' print >> out print >> out, '<!-- actual rate autocorrelation', xycorr, '-->' print >> out, '<!-- actual root height', v_to_age[r], '-->' print >> out, '<!-- actual log likelihood', ll, '-->' print >> out, '<!-- ll if rates were unity', ll_unity, '-->' print >> out print >> out, '<!--' print >> out, 'predefine the taxa as in' print >> out, 'http://beast.bio.ed.ac.uk/Introduction_to_XML_format' print >> out, '-->' print >> out, get_leaf_taxon_defn(list(string.uppercase[:nleaves])) print >> out print >> out, '<!--' print >> out, 'define the alignment as in' print >> out, 'http://beast.bio.ed.ac.uk/Introduction_to_XML_format' print >> out, '-->' print >> out, get_alignment_defn(leaves, N, v_to_seq) print >> out print >> out, '<!--' print >> out, 'specify the starting tree as in' print >> out, 'http://beast.bio.ed.ac.uk/Tutorial_4' print >> out, '-->' print >> out, get_starting_tree_defn(R, B, N_leaves) print >> out print >> out, '<!--' print >> out, 'connect the tree model as in' print >> out, 'http://beast.bio.ed.ac.uk/Tutorial_4' print >> out, '-->' print >> out, g_tree_model_defn print >> out print >> out, g_uncorrelated_relaxed_clock_info print >> out """ print >> out, '<!--' print >> out, 'create a list of taxa for which to constrain the mrca as in' print >> out, 'http://beast.bio.ed.ac.uk/Tutorial_3.1' print >> out, '-->' for v, leaves in sorted(v_to_leaves.items()): if len(leaves) > 1: print >> out, get_mrca_subset_defn(N, v, leaves) print >> out print >> out, '<!--' print >> out, 'create a tmrcaStatistic that will record the height as in' print >> out, 'http://beast.bio.ed.ac.uk/Tutorial_3.1' print >> out, '-->' for v, leaves in sorted(v_to_leaves.items()): if len(leaves) > 1: print >> out, get_mrca_stat_defn(N[v]) """ print >> out print >> out, g_likelihood_info print >> out print >> out, '<!--' print >> out, 'run the mcmc' print >> out, 'http://beast.bio.ed.ac.uk/Tutorial_3.1' print >> out, '-->' print >> out, get_mcmc_defn(v_to_leaves, v_to_age, N) print >> out print >> out, '</beast>' # return the response return out.getvalue()
def get_response_content(fs): # read the tree R, B, N = FtreeIO.newick_to_RBN(fs.tree) r = Ftree.R_to_root(R) T = Ftree.R_to_T(R) leaves = Ftree.T_to_leaves(T) internal_not_r = [v for v in Ftree.T_to_internal_vertices(T) if v is not r] # define the lists of leaves induced by the root vertex_partition = sorted(Ftree.R_to_vertex_partition(R)) vertex_lists = [sorted(p) for p in vertex_partition] leaf_set = set(leaves) leaf_lists = [sorted(s & leaf_set) for s in vertex_partition] # order the list of leaves in a nice block form leaves = [v for lst in leaf_lists for v in lst] # remove internal vertices by Schur complementation L_schur_rooted = Ftree.TB_to_L_schur(T, B, leaves + [r]) L_schur_full = Ftree.TB_to_L_schur(T, B, leaves) # show the matrix np.set_printoptions(linewidth=132) out = StringIO() # show the rooted schur complement w, v = scipy.linalg.eigh(L_schur_rooted) print >> out, 'rooted Schur complement:' print >> out, L_schur_rooted print >> out, 'Felsenstein weights at the root:' print >> out, -L_schur_rooted[-1][:-1] / L_schur_rooted[-1, -1] print >> out, 'rooted Schur complement eigendecomposition:' print >> out, w print >> out, v print >> out # show the full schur complement w, v = scipy.linalg.eigh(L_schur_full) print >> out, 'full Schur complement:' print >> out, L_schur_full print >> out, 'full Schur complement eigendecomposition:' print >> out, w print >> out, v print >> out # analyze perron components print >> out, 'perron components:' print >> out start = 0 for lst in leaf_lists: n = len(lst) C = L_schur_rooted[start:start + n, start:start + n] print >> out, 'C:' print >> out, C w_eff = np.sum(C) b_eff = 1 / w_eff print >> out, 'effective conductance:' print >> out, w_eff print >> out, 'effective branch length (or resistance or variance):' print >> out, b_eff S = np.linalg.pinv(C) print >> out, 'C^-1 (rooted covariance-like):' print >> out, S w, v = scipy.linalg.eigh(S) print >> out, 'rooted covariance-like eigendecomposition:' print >> out, w print >> out, v print >> out, 'perron value:' print >> out, w[-1] print >> out, 'reciprocal of perron value:' print >> out, 1 / w[-1] print >> out start += n print >> out # analyze subtrees print >> out, 'subtree Laplacian analysis:' print >> out start = 0 for lst in vertex_lists: n = len(lst) C = Ftree.TB_to_L_schur(T, B, lst + [r]) w, v = scipy.linalg.eigh(C) print >> out, 'subtree Laplacian:' print >> out, C print >> out, 'eigendecomposition:' print >> out, w print >> out, v print >> out start += n # analyze subtrees print >> out, 'full Schur complement subtree analysis:' print >> out start = 0 for lst in leaf_lists: n = len(lst) C = Ftree.TB_to_L_schur(T, B, lst + [r]) w, v = scipy.linalg.eigh(C) print >> out, 'full Schur complement in subtree:' print >> out, C print >> out, 'eigendecomposition:' print >> out, w print >> out, v print >> out start += n return out.getvalue()
def get_response_content(fs): # read the user input weight_delta_mu = fs.weight_delta_mu T, B, N = FtreeIO.newick_to_TBN(fs.newick) # summarize the tree leaves = Ftree.T_to_leaves(T) internal = Ftree.T_to_internal_vertices(T) vertices = leaves + internal nleaves = len(leaves) # define the fully connected schur complement graph as a Laplacian matrix # init the tree reconstruction state v_to_name = {} for v in leaves: name = N.get(v, None) if name is None: name = 'P' + chr(ord('a') + v) v_to_name[v] = name v_to_svs = dict((v, set([0])) for v in leaves) sv_to_vs = {0: set(leaves)} # define edge weights (used only for spectral split strategy) G = Ftree.TB_to_L_schur(T, B, leaves) # add some random amount to each edge weight for i in range(nleaves): for j in range(i): rate = 1 / fs.weight_delta_mu x = random.expovariate(rate) G[i, j] -= x G[j, i] -= x G[i, i] += x G[j, j] += x edge_to_weight = {} for index_pair in itertools.combinations(range(nleaves), 2): i, j = index_pair leaf_pair = (leaves[i], leaves[j]) edge_to_weight[frozenset(leaf_pair)] = -G[index_pair] # define pairwise distances (used only for nj split strategy) D = Ftree.TB_to_D(T, B, leaves) edge_to_distance = {} for index_pair in itertools.combinations(range(nleaves), 2): i, j = index_pair leaf_pair = (leaves[i], leaves[j]) edge_to_distance[frozenset(leaf_pair)] = D[index_pair] # pairs like (-(number of vertices in supervertex sv), supervertex sv) active_svs = set([0]) # initialize the sources of unique vertex and supervertex identifiers v_gen = itertools.count(max(leaves) + 1) sv_gen = itertools.count(1) # write the output out = StringIO() print >> out, '<html>' print >> out, '<body>' for count_pos in itertools.count(1): # add the graph rendering before the decomposition at this stage if fs.nj_split: edge_to_branch_weight = {} for k, v in edge_to_distance.items(): edge_to_branch_weight[k] = 1 / v elif fs.spectral_split: edge_to_branch_weight = edge_to_weight print >> out, '<div>' if fs.vis_star: print >> out, nhj.get_svg_star_components(active_svs, sv_to_vs, v_to_name, v_to_svs, edge_to_branch_weight) elif fs.vis_complete: print >> out, nhj.get_svg(active_svs, sv_to_vs, v_to_name, v_to_svs, edge_to_branch_weight) print >> out, '</div>' # update the splits next_active_svs = set() # svs can be decomposed independently in arbitrary order alpha_index_gen = itertools.count() for sv in active_svs: nstates = len(sv_to_vs[sv]) if nstates > 2: v_new = next(v_gen) sv_new_a = next(sv_gen) sv_new_b = next(sv_gen) alpha_index = next(alpha_index_gen) alpha = chr(ord('a') + alpha_index) v_to_name[v_new] = 'R%s%s' % (count_pos, alpha) next_active_svs.add(sv_new_a) next_active_svs.add(sv_new_b) if fs.spectral_split: if len(sv_to_vs[sv]) == 3: sv_new_c = next(sv_gen) nhj.delta_wye_transform(sv, v_to_svs, sv_to_vs, edge_to_weight, v_new, sv_new_a, sv_new_b, sv_new_c) next_active_svs.add(sv_new_c) else: nhj.harmonic_split_transform(sv, v_to_svs, sv_to_vs, edge_to_weight, v_new, sv_new_a, sv_new_b) elif fs.nj_split: sv_new_big = next(sv_gen) nhj.nj_split_transform(sv, v_to_svs, sv_to_vs, edge_to_distance, v_new, sv_new_big, sv_new_a, sv_new_b) next_active_svs.add(sv_new_big) elif nstates == 2: next_active_svs.add(sv) else: raise ValueError('supervertex has too few vertices') # if the set of active svs has not changed then we are done if active_svs == next_active_svs: break else: active_svs = next_active_svs print >> out, '</html>' print >> out, '</body>' return out.getvalue()
def get_response_content(fs): T, B, N = FtreeIO.newick_to_TBN(fs.tree) leaves = Ftree.T_to_leaves(T) L_schur = Ftree.TB_to_L_schur(T, B, leaves) mu = scipy.linalg.eigh(L_schur, eigvals_only=True)[1] return str(mu)
def get_response_content(fs): # read the tree R, B, N = FtreeIO.newick_to_RBN(fs.tree) r = Ftree.R_to_root(R) T = Ftree.R_to_T(R) leaves = Ftree.T_to_leaves(T) internal_not_r = [v for v in Ftree.T_to_internal_vertices(T) if v is not r] # define the lists of leaves induced by the root vertex_partition = sorted(Ftree.R_to_vertex_partition(R)) vertex_lists = [sorted(p) for p in vertex_partition] leaf_set = set(leaves) leaf_lists = [sorted(s & leaf_set) for s in vertex_partition] # order the list of leaves in a nice block form leaves = [v for lst in leaf_lists for v in lst] # remove internal vertices by Schur complementation L_schur_rooted = Ftree.TB_to_L_schur(T, B, leaves + [r]) L_schur_full = Ftree.TB_to_L_schur(T, B, leaves) # show the matrix np.set_printoptions(linewidth=132) out = StringIO() # show the rooted schur complement w, v = scipy.linalg.eigh(L_schur_rooted) print >> out, 'rooted Schur complement:' print >> out, L_schur_rooted print >> out, 'Felsenstein weights at the root:' print >> out, -L_schur_rooted[-1][:-1] / L_schur_rooted[-1, -1] print >> out, 'rooted Schur complement eigendecomposition:' print >> out, w print >> out, v print >> out # show the full schur complement w, v = scipy.linalg.eigh(L_schur_full) print >> out, 'full Schur complement:' print >> out, L_schur_full print >> out, 'full Schur complement eigendecomposition:' print >> out, w print >> out, v print >> out # analyze perron components print >> out, 'perron components:' print >> out start = 0 for lst in leaf_lists: n = len(lst) C = L_schur_rooted[start:start+n, start:start+n] print >> out, 'C:' print >> out, C w_eff = np.sum(C) b_eff = 1 / w_eff print >> out, 'effective conductance:' print >> out, w_eff print >> out, 'effective branch length (or resistance or variance):' print >> out, b_eff S = np.linalg.pinv(C) print >> out, 'C^-1 (rooted covariance-like):' print >> out, S w, v = scipy.linalg.eigh(S) print >> out, 'rooted covariance-like eigendecomposition:' print >> out, w print >> out, v print >> out, 'perron value:' print >> out, w[-1] print >> out, 'reciprocal of perron value:' print >> out, 1 / w[-1] print >> out start += n print >> out # analyze subtrees print >> out, 'subtree Laplacian analysis:' print >> out start = 0 for lst in vertex_lists: n = len(lst) C = Ftree.TB_to_L_schur(T, B, lst + [r]) w, v = scipy.linalg.eigh(C) print >> out, 'subtree Laplacian:' print >> out, C print >> out, 'eigendecomposition:' print >> out, w print >> out, v print >> out start += n # analyze subtrees print >> out, 'full Schur complement subtree analysis:' print >> out start = 0 for lst in leaf_lists: n = len(lst) C = Ftree.TB_to_L_schur(T, B, lst + [r]) w, v = scipy.linalg.eigh(C) print >> out, 'full Schur complement in subtree:' print >> out, C print >> out, 'eigendecomposition:' print >> out, w print >> out, v print >> out start += n return out.getvalue()