int test_nodes_from_labels() { const char *test_name = "test_nodes_from_labels"; struct rooted_tree tree = tree_3(); struct llist *labels = create_llist(); append_element(labels, "C"); append_element(labels, "f"); append_element(labels, "D"); append_element(labels, "A"); struct llist *nodes = nodes_from_labels(&tree, labels); struct list_elem *el = nodes->head; if (strcmp(((struct rnode *) el->data)->label, "C") != 0) { printf ("%s: expected label 'C', got '%s'\n", test_name, ((struct rnode *) el->data)->label); return 1; } el = el->next; if (strcmp(((struct rnode *) el->data)->label, "f") != 0) { printf ("%s: expected label 'f', got '%s'\n", test_name, ((struct rnode *) el->data)->label); return 1; } el = el->next; if (strcmp(((struct rnode *) el->data)->label, "D") != 0) { printf ("%s: expected label 'D', got '%s'\n", test_name, ((struct rnode *) el->data)->label); return 1; } el = el->next; if (strcmp(((struct rnode *) el->data)->label, "A") != 0) { printf ("%s: expected label 'A', got '%s'\n", test_name, ((struct rnode *) el->data)->label); return 1; } el = el->next; if (NULL != el) { printf ("%s: nodes list not terminated.\n", test_name); return 1; } printf ("%s: ok.\n", test_name); return 0; }
int main(int argc, char *argv[]) { struct rooted_tree *tree; struct parameters params; struct h_data depths; params = get_params(argc, argv); /* I could take the switch out of the loop, since the distance type * is fixed for the process's lifetime. OTOH the code is easier to * understand this way, and it's unlikely the switch has a visible * impact on performance. */ while ((tree = parse_tree()) != NULL) { alloc_simple_node_pos(tree); depths = set_node_depth_cb(tree, set_simple_node_pos_depth, get_simple_node_pos_depth); if (FAILURE == depths.status) { perror(NULL); exit(EXIT_FAILURE); } struct rnode *lca_node; struct llist *selected_nodes; if (ARGV_LABELS == params.selection) { selected_nodes = nodes_from_labels(tree, params.labels); if (NULL == selected_nodes) { perror(NULL); exit(EXIT_FAILURE); } } else { selected_nodes = get_selected_nodes(tree, params.selection); } switch (params.distance_method) { case FROM_ROOT: print_distance_list(tree->root, selected_nodes, params.list_orientation, params.show_header); break; case FROM_LCA: /* if no lbl given, use root as LCA */ /* I don't remember why I did it like that, and I * don't see what it is good for, so I discard it. */ /* if (0 == params.labels->count) { lca_node = tree->root; } else { lca_node = lca_from_nodes(tree, selected_nodes); } */ lca_node = lca_from_nodes(tree, selected_nodes); if (NULL == lca_node) { perror(NULL); exit(EXIT_FAILURE); } print_distance_list(lca_node, selected_nodes, params.list_orientation, params.show_header); break; case MATRIX: switch (params.matrix_shape) { case SQUARE: print_square_distance_matrix(tree, selected_nodes, params.show_header); break; case TRIANGLE: print_triangular_distance_matrix(tree, selected_nodes, params.show_header); break; default: fprintf(stderr, "ERROR: unknown matrix form %d\n", params.matrix_shape); exit(EXIT_FAILURE); } break; case FROM_PARENT: print_distance_list(NULL, selected_nodes, params.list_orientation, params.show_header); break; default: fprintf (stderr, "ERROR: invalid distance type '%d'.\n", params.distance_method); exit(EXIT_FAILURE); } destroy_llist(selected_nodes); destroy_all_rnodes(NULL); destroy_tree(tree); } destroy_llist(params.labels); return 0; }
void process_tree(struct rooted_tree *tree, struct parameters params) { struct llist *descendants; switch (params.mode) { case EXACT: descendants = nodes_from_labels(tree, params.labels); if (NULL == descendants) { perror(NULL); exit(EXIT_FAILURE); } if (0 == descendants->count) { fprintf (stderr, "WARNING: no label matches.\n"); /* I don't consider this a failure: it is just the case * that the tree does not contain the specified labels. * */ exit(EXIT_SUCCESS); } break; case REGEXP: descendants = nodes_from_regexp(tree, params.regexp); if (NULL == descendants) { perror(NULL); exit(EXIT_FAILURE); } if (0 == descendants->count) { fprintf (stderr, "WARNING: no match for regexp /%s/\n", params.regexp_string); exit(EXIT_SUCCESS); /** see above */ } break; default: fprintf (stderr, "Unknown mode %d\n", params.mode); exit(EXIT_FAILURE); } /* We need a copy b/c lca() modifies its arg */ struct llist *desc_clone = shallow_copy(descendants); if (NULL == desc_clone) { perror(NULL); exit(EXIT_FAILURE); } struct rnode *subtree_root = lca(tree, desc_clone); if (NULL == subtree_root) { perror(NULL); exit(EXIT_FAILURE); } free(desc_clone); /* elems freed in lca() */ /* Jump up tree to get context, if any was required ('context' > 0) */ int context; for (context = params.context; context > 0; context--) if (! is_root(subtree_root)) subtree_root = subtree_root->parent; // TODO: could not replace to_newick() by dump_newick() due to side // effects. Investigate. if (NULL != subtree_root) { if ((! params.check_monophyly) || (is_monophyletic(descendants, subtree_root))) { /* monophyly of input labels is verified or not * requested */ char *newick; if (params.siblings) { struct llist *sibs = siblings(subtree_root); if (NULL == sibs) { perror(NULL); exit(EXIT_FAILURE); } struct list_elem *el; for (el=sibs->head;NULL!=el;el=el->next) { struct rnode *sib; sib = el->data; newick = to_newick(sib); printf ("%s\n", newick); free(newick); } destroy_llist(sibs); } else { /* normal operation: print clade defined by * labels. */ newick = to_newick(subtree_root); printf ("%s\n", newick); free(newick); } } } else { fprintf (stderr, "WARNING: LCA not found\n"); } destroy_llist(descendants); }