def get_response_content(fs): # check input compatibility if fs.nvertices < fs.naxes+1: msg_a = 'attempting to plot too many eigenvectors ' msg_b = 'for the given number of vertices' raise ValueError(msg_a + msg_b) # define the requested physical size of the images (in pixels) physical_size = (640, 480) # get the points L = create_laplacian_matrix(fs.nvertices) D = Euclid.laplacian_to_edm(L) HSH = Euclid.edm_to_dccov(D) W, VT = np.linalg.eigh(HSH) V = VT.T.tolist() if fs.eigenvalue_scaling: vectors = [np.array(v)*w for w, v in list(reversed(sorted(zip(np.sqrt(W), V))))[:-1]] else: vectors = [np.array(v) for w, v in list(reversed(sorted(zip(np.sqrt(W), V))))[:-1]] X = np.array(zip(*vectors)) # transform the points to eigenfunctions such that the first point is positive F = X.T[:fs.naxes] for i in range(fs.naxes): if F[i][0] < 0: F[i] *= -1 # draw the image try: ext = Form.g_imageformat_to_ext[fs.imageformat] return create_image_string(ext, physical_size, F, fs.xaxis_length) except CairoUtil.CairoUtilError as e: raise HandlingError(e)
def get_splits(initial_distance_matrix, split_function, update_function, on_label_split=None): """ This is the most external of the functions in this module. Get the set of splits implied by the tree that would be reconstructed. @param initial_distance_matrix: a distance matrix @param split_function: takes a distance matrix and returns an index split @param update_function: takes a distance matrix and an index subset and returns a distance matrix @param on_label_split: notifies the caller of the label split induced by an index split @return: a set of splits """ n = len(initial_distance_matrix) # keep a stack of (label_set_per_vertex, distance_matrix) pairs initial_state = ([set([i]) for i in range(n)], initial_distance_matrix) stack = [initial_state] # process the stack in a depth first manner, building the split set label_split_set = set() while stack: label_sets, D = stack.pop() # if the matrix is small then we are done if len(D) < 4: continue # split the indices using the specified function try: index_split = split_function(D) # convert the index split to a label split label_split = index_split_to_label_split(index_split, label_sets) # notify the caller if a callback is requested if on_label_split: on_label_split(label_split) # add the split to the master set of label splits label_split_set.add(label_split) # for large matrices create the new label sets and the new conformant distance matrices a, b = index_split for index_selection, index_complement in ((a, b), (b, a)): if len(index_complement) > 2: next_label_sets = SchurAlgebra.vmerge( label_sets, index_selection) next_D = update_function(D, index_selection) next_state = (next_label_sets, next_D) stack.append(next_state) except DegenerateSplitException, e: # we cannot recover from a degenerate split unless there are more than four indices if len(D) <= 4: continue # with more than four indices we can fall back to partial splits index_set = set([e.index]) # get the next label sets next_label_sets = SchurAlgebra.vdelete(label_sets, index_set) # get the next conformant distance matrix by schur complementing out the offending index L = Euclid.edm_to_laplacian(D) L_small = SchurAlgebra.mschur(L, index_set) next_D = Euclid.laplacian_to_edm(L_small) next_state = (next_label_sets, next_D) stack.append(next_state)
def update_using_laplacian(D, index_set): """ Update the distance matrix by summing rows and columns of the removed indices. @param D: the distance matrix @param index_set: the set of indices that will be removed from the updated distance matrix @return: an updated distance matrix """ L = Euclid.edm_to_laplacian(D) L_small = SchurAlgebra.mmerge(L, index_set) D_small = Euclid.laplacian_to_edm(L_small) return D_small
def get_splits(initial_distance_matrix, split_function, update_function, on_label_split=None): """ This is the most external of the functions in this module. Get the set of splits implied by the tree that would be reconstructed. @param initial_distance_matrix: a distance matrix @param split_function: takes a distance matrix and returns an index split @param update_function: takes a distance matrix and an index subset and returns a distance matrix @param on_label_split: notifies the caller of the label split induced by an index split @return: a set of splits """ n = len(initial_distance_matrix) # keep a stack of (label_set_per_vertex, distance_matrix) pairs initial_state = ([set([i]) for i in range(n)], initial_distance_matrix) stack = [initial_state] # process the stack in a depth first manner, building the split set label_split_set = set() while stack: label_sets, D = stack.pop() # if the matrix is small then we are done if len(D) < 4: continue # split the indices using the specified function try: index_split = split_function(D) # convert the index split to a label split label_split = index_split_to_label_split(index_split, label_sets) # notify the caller if a callback is requested if on_label_split: on_label_split(label_split) # add the split to the master set of label splits label_split_set.add(label_split) # for large matrices create the new label sets and the new conformant distance matrices a, b = index_split for index_selection, index_complement in ((a, b), (b, a)): if len(index_complement) > 2: next_label_sets = SchurAlgebra.vmerge(label_sets, index_selection) next_D = update_function(D, index_selection) next_state = (next_label_sets, next_D) stack.append(next_state) except DegenerateSplitException, e: # we cannot recover from a degenerate split unless there are more than four indices if len(D) <= 4: continue # with more than four indices we can fall back to partial splits index_set = set([e.index]) # get the next label sets next_label_sets = SchurAlgebra.vdelete(label_sets, index_set) # get the next conformant distance matrix by schur complementing out the offending index L = Euclid.edm_to_laplacian(D) L_small = SchurAlgebra.mschur(L, index_set) next_D = Euclid.laplacian_to_edm(L_small) next_state = (next_label_sets, next_D) stack.append(next_state)
def get_response_content(fs): # read the matrix D = fs.matrix # read the ordered labels ordered_labels = Util.get_stripped_lines(StringIO(fs.labels)) if not ordered_labels: raise HandlingError('no ordered taxa were provided') if len(ordered_labels) != len(set(ordered_labels)): raise HandlingError('the ordered taxa should be unique') # get the label selection and its complement min_selected_labels = 2 min_unselected_labels = 1 selected_labels = set(Util.get_stripped_lines(StringIO(fs.selection))) if len(selected_labels) < min_selected_labels: raise HandlingError('at least %d taxa should be selected to be grouped' % min_selected_labels) # get the set of labels in the complement unselected_labels = set(ordered_labels) - selected_labels if len(unselected_labels) < min_unselected_labels: raise HandlingError('at least %d taxa should remain outside the selected group' % min_unselected_labels) # assert that no bizarre labels were selected weird_labels = selected_labels - set(ordered_labels) if weird_labels: raise HandlingError('some selected taxa are invalid: ' + str(weird_labels)) # assert that the size of the distance matrix is compatible with the number of ordered labels if len(D) != len(ordered_labels): raise HandlingError('the number of listed taxa does not match the number of rows in the distance matrix') # get the set of selected indices and its complement n = len(D) index_selection = set(i for i, label in enumerate(ordered_labels) if label in selected_labels) index_complement = set(range(n)) - index_selection # begin the response out = StringIO() # get the ordered list of sets of indices to merge merged_indices = SchurAlgebra.vmerge([set([x]) for x in range(n)], index_selection) # calculate the new distance matrix L = Euclid.edm_to_laplacian(D) L_merged = SchurAlgebra.mmerge(L, index_selection) D_merged = Euclid.laplacian_to_edm(L_merged) # print the output distance matrix and the labels of its rows print >> out, 'new distance matrix:' print >> out, MatrixUtil.m_to_string(D_merged) print >> out print >> out, 'new taxon labels:' for merged_index_set in merged_indices: if len(merged_index_set) == 1: print >> out, ordered_labels[merged_index_set.pop()] else: print >> out, '{' + ', '.join(selected_labels) + '}' # write the response return out.getvalue()
def get_response_content(fs): # read the matrix L = fs.laplacian # read the ordered labels ordered_labels = Util.get_stripped_lines(StringIO(fs.labels)) if not ordered_labels: raise HandlingError('no ordered taxa were provided') if len(ordered_labels) != len(set(ordered_labels)): raise HandlingError('the ordered taxa should be unique') # get the label selection and its complement min_selected_labels = 2 min_unselected_labels = 1 selected_labels = set(Util.get_stripped_lines(StringIO(fs.selection))) if len(selected_labels) < min_selected_labels: raise HandlingError('at least %d taxa should be selected to be grouped' % min_selected_labels) # get the set of labels in the complement unselected_labels = set(ordered_labels) - selected_labels if len(unselected_labels) < min_unselected_labels: raise HandlingError('at least %d taxa should remain outside the selected group' % min_unselected_labels) # assert that no bizarre labels were selected weird_labels = selected_labels - set(ordered_labels) if weird_labels: raise HandlingError('some selected taxa are invalid: ' + str(weird_labels)) # assert that the size of the distance matrix is compatible with the number of ordered labels if len(L) != len(ordered_labels): raise HandlingError('the number of listed taxa does not match the number of rows in the distance matrix') # get the set of selected indices and its complement n = len(L) index_selection = set(i for i, label in enumerate(ordered_labels) if label in selected_labels) index_complement = set(range(n)) - index_selection # begin the response out = StringIO() # calculate the new laplacian matrix L_small = SchurAlgebra.mschur(L, index_selection) D_small = Euclid.laplacian_to_edm(L_small) # print the matrices and the labels of its rows print >> out, 'new laplacian matrix:' print >> out, MatrixUtil.m_to_string(L_small) print >> out print >> out, 'new distance matrix:' print >> out, MatrixUtil.m_to_string(D_small) print >> out print >> out, 'new taxon labels:' for index in sorted(index_complement): print >> out, ordered_labels[index] # write the response return out.getvalue()
def process(npoints, nseconds): """ @param npoints: attempt to form each counterexample from this many points @param nseconds: allow this many seconds to run @return: a multi-line string that summarizes the results """ start_time = time.time() best_result = None nchecked = 0 while time.time() - start_time < nseconds: # look for a counterexample points = sample_points(npoints) D = points_to_edm(points) L = Euclid.edm_to_laplacian(D) L_small = SchurAlgebra.mmerge(L, set([0, 1])) w = np.linalg.eigvalsh(L_small) D_small = Euclid.laplacian_to_edm(L_small) result = Counterexample(points, D, w, D_small) # see if the counterexample is interesting if best_result is None: best_result = result elif min(result.L_eigenvalues) < min(best_result.L_eigenvalues): best_result = result nchecked += 1 out = StringIO() print >> out, 'checked', nchecked, 'matrices each formed from', npoints, 'points' print >> out print >> out, 'eigenvalues of the induced matrix with lowest eigenvalue:' for value in reversed(sorted(best_result.L_eigenvalues)): print >> out, value print >> out print >> out, 'corresponding induced distance matrix:' print >> out, MatrixUtil.m_to_string(best_result.D_small) print >> out print >> out, 'the original distance matrix corresponding to this matrix:' print >> out, MatrixUtil.m_to_string(best_result.D) print >> out print >> out, 'the points that formed the original distance matrix:' for point in best_result.points: print >> out, '\t'.join(str(x) for x in point) return out.getvalue().strip()
def get_response_content(fs): A = fs.matrix L = Euclid.adjacency_to_laplacian(A) D = Euclid.laplacian_to_edm(L) return MatrixUtil.m_to_string(D) + "\n"