func treeClusters( threshold float64, dists *intern.Table, tree *newick.Tree, ) clusters { if len(tree.Children) == 0 { if len(tree.Label) > 0 { return clusters{[]string{tree.Label}} } return nil } // Compare all pairs in this tree. If all are within the threshold given, // then add this subtree as a cluster and move on. Otherwise, dig deeper. within := forNode(tree, func(node1 *newick.Tree) bool { if len(node1.Label) == 0 { return true } a1 := dists.Atom(node1.Label) return forNode(tree, func(node2 *newick.Tree) bool { if len(node2.Label) == 0 { return true } return dists.Get(a1, dists.Atom(node2.Label)) <= threshold }) }) if within { cluster := make([]string, 0, 10) forNode(tree, func(node *newick.Tree) bool { if len(node.Label) == 0 { return true } cluster = append(cluster, node.Label) return true }) return clusters{cluster} } clusters := make(clusters, 0, len(tree.Children)) for i := range tree.Children { clusters = append( clusters, treeClusters(threshold, dists, &tree.Children[i])...) } return clusters }
func dist(matrix *intern.Table, d1, d2 string) float64 { return matrix.Get(matrix.Atom(d1), matrix.Atom(d2)) }