Exemple #1
0
 def __init__(self, T, B):
     """
     @param T: tree topology
     @param B: branch lengths
     """
     self.T = T
     self.B = B
     # define a leaf and internal vertex order
     self.leaves = Ftree.T_to_leaves(self.T)
     self.internal = Ftree.T_to_internal_vertices(self.T)
     # compute the reference MDS for canonical reflection
     D = Ftree.TB_to_D(self.T, self.B, self.leaves)
     self.reference_MDS = self._D_to_MDS(D)
Exemple #2
0
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)
Exemple #3
0
 def get_full_distance_MDS(self):
     """
     Reflect towards the reference MDS.
     This is similar to the leaf MDS but for the full distance matrix.
     @return: Nx2 MDS matrix
     """
     D_full = Ftree.TB_to_D(self.T, self.B, self.vertices)
     G_neg = MatrixUtil.double_centered(D_full) / 2.0
     W_neg, V = scipy.linalg.eigh(G_neg, eigvals=(0,1))
     MDS = V * np.sqrt(np.abs(W_neg))
     # compute signs of dot products of corresponding columns
     signs = []
     nleaves = len(self.leaves)
     for a, b in zip(MDS[:nleaves].T, self.reference_leaf_MDS.T):
         signs.append(1 if np.dot(a, b) > 0 else -1)
     # return a copy of the MDS with the new signs
     return np.array(MDS) * signs
Exemple #4
0
 def get_reference_leaf_MDS(self):
     """
     Let the MDS be an Nx2 matrix of scaled points.
     The points should be appropriately scaled by eigenvalues.
     The reflections (column signs) of the points are arbitrary.
     The points should be ordered conformantly with the NxN distance matrix.
     @param D: NxN distance matrix
     @return: Nx2 MDS matrix
     """
     D_leaves = Ftree.TB_to_D(self.T, self.B, self.leaves)
     G_neg = MatrixUtil.double_centered(D_leaves) / 2.0
     # Get eigenvalues in increasing order as W,
     # and get corresponding eigenvectors as columns of V.
     W_neg, V = scipy.linalg.eigh(G_neg, eigvals=(0,1))
     # Scale columns by square root of negative eigenvalue.
     # Use absolute value to hackily deal with non-Euclidean
     # distance matrices which may arise as a result of
     # adding a perturbation.
     return V * np.sqrt(np.abs(W_neg))
Exemple #5
0
 def __init__(self, T, B, N, label_mode):
     """
     @param T: tree topology
     @param B: branch lengths
     @param N: vertex to name
     @param label_mode: this is an option for MDS vertex labels
     """
     # store tree characteristics
     self.T = T
     self.B = B
     self.N = N
     # store options
     self.label_mode = label_mode
     # define a leaf and internal vertex order
     self.leaves = Ftree.T_to_leaves(self.T)
     self.internal = Ftree.T_to_internal_vertices(self.T)
     self.vertices = self.leaves + self.internal
     # map vertices to short names
     self.N_short = dict(zip(self.vertices, gen_short_names()))
     # compute the reference MDS for canonical reflection
     D_leaves = Ftree.TB_to_D(self.T, self.B, self.leaves)
     self.reference_leaf_MDS = self.get_reference_leaf_MDS()
Exemple #6
0
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()
Exemple #7
0
def get_full_distance_MDS(T, B, vertices):
    D_full = Ftree.TB_to_D(T, B, vertices)
    G_neg = MatrixUtil.double_centered(D_full) / 2.0
    W_neg, V = scipy.linalg.eigh(G_neg, eigvals=(0, 1))
    return V * np.sqrt(np.abs(W_neg))
Exemple #8
0
 def _get_D(self):
     """
     @return: distance matrix relating leaves
     """
     return Ftree.TB_to_D(self.T, self.B, self.leaves)