예제 #1
0
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;
}
예제 #2
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;
}
예제 #3
0
파일: subtree.c 프로젝트: gatoravi/MFAST
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);

}