31 if (input_trees.
empty()) {
32 error =
"no trees given";
37 for (
size_t i = 0; !error && i<input_trees.
size(); ++i) {
47 GB_warningf(
"while loading tree '%s':\n%s", input_trees[i], warnings);
50 tree_builder.
add(tree, input_trees[i], weight);
54 if (!error) consense_tree = tree_builder.
get(different_species, error);
57 arb_assert(contradicted(consense_tree, error));
66 const char *lslash = strrchr(savename,
'/');
67 if (lslash) savename = lslash+1;
69 const char *ldot = strrchr(savename,
'.');
72 if (tree_name[0] == 0) freedup(tree_name,
"tree_consensus");
115 error =
GBS_global_string(
"Failed to save tree to '%s' (Reason: %s)", savename, error);
125 printf(
"Usage: arb_consensus_tree [options] [tree]+\n"
126 "Purpose: Create a consensus tree out of multiple trees\n"
128 " -w outfile write consensus tree to outfile\n");
137 char *savename =
NULp;
141 for (
int a = 1; a<argc; ++a) {
142 const char *arg = argv[a];
145 case 'w': savename =
ARB_strdup(argv[++a]);
break;
150 input_tree_names.
put(argv[a]);
154 if (!error && input_tree_names.
empty()) error =
"no input trees specified";
157 size_t species_count;
166 double percent =
size_t((leafs*1000)/species_count)/10.0;
168 printf(
"Generated tree contains %.1f%% of species (%zu of %zu found in input trees)\n",
169 percent, leafs, species_count);
175 printf(
"successfully created consensus tree\n"
176 "(no savename specified -> tree not saved)\n");
187 printf(
"Error in arb_consensus_tree: %s\n", error);
204 static char *custom_tree_name(
int dir,
const char *name) {
return GBS_global_string_copy(
"consense/%i/%s.tree", dir, name); }
205 static char *custom_numbered_tree_name(
int dir,
const char *name,
int treeNr) {
return GBS_global_string_copy(
"consense/%i/%s_%i.tree", dir, name, treeNr); }
207 static void add_inputnames(StrArray& to,
int dir,
const char *basename,
int first_tree,
int last_tree) {
208 for (
int t = first_tree; t <= last_tree; ++t) {
209 to.put(custom_numbered_tree_name(dir, basename, t));
214 if (tree->
is_leaf())
return 0.0;
218 calc_intree_distance(tree->get_leftson()) +
219 calc_intree_distance(tree->get_rightson());
222 #define LENSUM_EPSILON .000001
237 return all().ofgroup(expected);
240 static arb_test::match_expectation build_expected_consensus_tree(
const int treedir,
const char *basename,
int first_tree,
int last_tree,
double weight,
const char *outbasename,
size_t expected_species_count,
double expected_intree_distance) {
246 StrArray input_tree_names;
247 add_inputnames(input_tree_names, treedir, basename, first_tree, last_tree);
249 size_t species_count;
252 expected.
add(consense_tree_generated(tree, error, species_count, expected_species_count, expected_intree_distance));
254 char *saveas = custom_tree_name(treedir, outbasename);
259 char *expected_save = custom_tree_name(treedir,
GBS_global_string(
"%s_expected", outbasename));
262 #if defined(TEST_AUTO_UPDATE)
263 if (!exported_as_expected) {
264 TEST_COPY_FILE(saveas, expected_save);
266 #else // !defined(TEST_AUTO_UPDATE)
277 return all().ofgroup(expected);
280 void TEST_consensus_tree_1() {
281 TEST_EXPECTATION(build_expected_consensus_tree(1,
"bootstrapped", 1, 5, 0.7,
"consense1", 22, 0.925779));
284 void TEST_consensus_tree_1_single() {
285 TEST_EXPECTATION(build_expected_consensus_tree(1,
"bootstrapped", 1, 1, 0.01,
"consense1_single", 22, 0.924610));
289 void TEST_consensus_tree_2() {
290 TEST_EXPECTATION(build_expected_consensus_tree(2,
"bootstrapped", 1, 4, 2.5,
"consense2", 59, 2.849827));
294 void TEST_consensus_tree_3() {
295 TEST_EXPECTATION(build_expected_consensus_tree(3,
"bootstrapped", 1, 3, 137.772,
"consense3", 128, 2.170685));
299 void TEST_consensus_tree_from_disjunct_trees() {
300 TEST_EXPECTATION(build_expected_consensus_tree(4,
"disjunct", 1, 2, 137.772,
"disjunct_merged", 15, 2.034290));
304 void TEST_consensus_tree_from_partly_overlapping_trees() {
308 TEST_EXPECTATION(build_expected_consensus_tree(4,
"disjunct", 1, 3, 137.772,
"overlap_merged", 15, 2.596455));
312 void TEST_consensus_tree_from_minimal_overlapping_trees() {
314 TEST_EXPECTATION(build_expected_consensus_tree(4,
"disjunct", 0, 2, 137.772,
"overlap_mini_merged", 15, 2.750745));
318 void TEST_consensus_tree_described_in_arbhelp() {
320 TEST_EXPECTATION(build_expected_consensus_tree(5,
"help", 1, 2, 2.0,
"help_merged", 6, 1.050000));
324 void TEST_consensus_tree_from_trees_overlapping_by_twothirds() {
328 TEST_EXPECTATION(build_expected_consensus_tree(6,
"overlap_two_thirds", 1, 3, 19.2,
"overlap_twothirds_merged", 15, 3.561680));
332 void TEST_consensus_tree_from_mostly_overlapping_trees() {
335 TEST_EXPECTATION(build_expected_consensus_tree(7,
"disjunct_del2", 1, 3, 137.772,
"overlap_mostly", 15, 1.820057));
339 void TEST_consensus_tree_from_mostly_overlapping_trees_2() {
342 TEST_EXPECTATION(build_expected_consensus_tree(8,
"overlap2", 1, 3, 137.772,
"overlap2_mostly", 8, 0.529109));
345 TEST_PUBLISH(TEST_consensus_tree_from_mostly_overlapping_trees_2);
348 #define REPEATED_TESTS
350 #if defined(REPEATED_TESTS)
351 void TEST_consensus_tree_generation_is_deterministic() {
352 TEST_consensus_tree_described_in_arbhelp();
353 TEST_consensus_tree_from_minimal_overlapping_trees();
354 TEST_consensus_tree_from_partly_overlapping_trees();
355 TEST_consensus_tree_from_disjunct_trees();
356 TEST_consensus_tree_3();
357 TEST_consensus_tree_2();
358 TEST_consensus_tree_1_single();
359 TEST_consensus_tree_1();
362 void TEST_arb_consensus_tree() {
367 char *saveas = custom_tree_name(1,
"consense1");
368 char *expected = custom_tree_name(1,
"consense1_expected");
371 " -w consense/1/consense1.tree"
372 " consense/1/bootstrapped_1.tree"
373 " consense/1/bootstrapped_2.tree"
374 " consense/1/bootstrapped_3.tree"
375 " consense/1/bootstrapped_4.tree"
376 " consense/1/bootstrapped_5.tree",
378 "Created new database \"\"");
388 char *saveas = custom_tree_name(2,
"consense2");
389 char *expected = custom_tree_name(2,
"consense2_expected");
392 " -w consense/2/consense2.tree"
393 " consense/2/bootstrapped_1.tree"
394 " consense/2/bootstrapped_2.tree"
395 " consense/2/bootstrapped_3.tree"
396 " consense/2/bootstrapped_4.tree",
398 "Created new database \"\"");
407 #endif // REPEATED_TESTS
413 static const char *findFirstNameContaining(
TreeNode *tree,
const char *part) {
414 const char *found =
NULp;
415 if (tree->
name && strstr(tree->
name, part)) {
419 found = findFirstNameContaining(tree->get_leftson(), part);
420 if (!found) found = findFirstNameContaining(tree->get_rightson(), part);
425 void TEST_SLOW_treeIO_stable() {
426 const char *dbname =
"trees/bootstrap_groups.arb";
427 const char *treename =
"tree_bootstrap_and_groups";
428 const char *savename =
"bg";
437 for (
int save_branchlengths = 0; save_branchlengths <= 1; ++save_branchlengths) {
438 for (
int save_bootstraps = 0; save_bootstraps <= 1; ++save_bootstraps) {
439 for (
int save_groupnames = 0; save_groupnames <= 1; ++save_groupnames) {
440 bool quoting_occurs = save_bootstraps && save_groupnames;
441 for (
int pretty = 0; pretty <= 1; ++pretty) {
448 save_bootstraps ?
"Bs" :
"",
449 save_groupnames ?
"Grp" :
"",
450 save_branchlengths ?
"Len" :
"",
457 GB_ERROR export_error =
TREE_write_Newick(gb_main, treename, labels_use_IDs, save_branchlengths, save_bootstraps, save_groupnames, pretty, quoteMode, outfile);
463 #if defined(TREEIO_AUTO_UPDATE)
465 #else // !defined(TREEIO_AUTO_UPDATE)
467 #if defined(TREEIO_AUTO_UPDATE_IF_EXPORT_DIFFERS)
468 if (!exported_as_expected) {
471 #else // !defined(TREEIO_AUTO_UPDATE_IF_EXPORT_DIFFERS)
476 const char *reloaded_treename =
"tree_reloaded";
478 char *comment =
NULp;
492 if (save_groupnames) {
493 const char *quotedGroup = findFirstNameContaining(tree,
"quoted");
494 const char *underscoreGroup = findFirstNameContaining(tree,
"bs100");
498 const char *capsLeaf = findFirstNameContaining(tree,
"Caps");
507 GB_ERROR reexport_error =
TREE_write_Newick(gb_main, reloaded_treename, labels_use_IDs, save_branchlengths, save_bootstraps, save_groupnames, pretty, quoteMode, outfile);
515 " | grep -v 'Loaded from trees/.*_exp_'"
516 " | grep -v 'tree_reloaded saved to'"
517 " > %s", outfile, outfile2);
524 #if defined(TREEIO_AUTO_UPDATE_IF_REEXPORT_DIFFERS)
525 if (!reexported_as_expected) {
528 #else // !defined(TREEIO_AUTO_UPDATE_IF_REEXPORT_DIFFERS)
550 void TEST_CONSENSUS_TREE_functionality() {
553 char *comment =
NULp;
555 SizeAwareTree *tree =
DOWNCAST(SizeAwareTree*,
TREE_load(
"trees/bg_exp_p_GrpLen_0.tree",
557 &comment,
false,
NULp));
560 #define ORG_1111 "(AticSea6,(RblAerol,RblMesop))"
561 #define TOP_1111 "((RblAerol,RblMesop),AticSea6)"
562 #define BOT_1111 ORG_1111
564 #define ORG_11121 "((DnrShiba,RsbElon4),MmbAlkal)"
565 #define TOP_11121 ORG_11121
566 #define BOT_11121 "(MmbAlkal,(DnrShiba,RsbElon4))"
568 #define ORG_11122 "((MabPelag,MabSalin),PaoMaris)"
569 #define TOP_11122 ORG_11122
570 #define BOT_11122 "(PaoMaris,(MabPelag,MabSalin))"
572 #define ORG_1112 "(" ORG_11121 "," ORG_11122 ")"
573 #define TOP_1112 "(" TOP_11121 "," TOP_11122 ")"
574 #define BOT_1112 "(" BOT_11121 "," BOT_11122 ")"
575 #define EDG_1112 "(" TOP_11121 "," BOT_11122 ")"
577 #define ORG_111 "(" ORG_1111 "," ORG_1112 ")"
578 #define TOP_111 "(" TOP_1112 "," TOP_1111 ")"
579 #define BOT_111 "(" BOT_1111 "," BOT_1112 ")"
580 #define EDG_111 "(" EDG_1112 "," BOT_1111 ")"
582 #define ORG_112 "(OnlGran2,RsnAnta2)"
583 #define TOP_112 ORG_112
584 #define BOT_112 ORG_112
586 #define ORG_11 "(" ORG_111 "," ORG_112 ")"
587 #define TOP_11 "(" TOP_111 "," TOP_112 ")"
588 #define BOT_11 "(" BOT_112 "," BOT_111 ")"
589 #define EDG_11 "(" EDG_111 "," BOT_112 ")"
591 #define ORG_12 "(_MhuCaps,ThtNivea)"
592 #define TOP_12 "(ThtNivea,_MhuCaps)"
593 #define BOT_12 TOP_12
595 #define ORG_1 "(" ORG_11 "," ORG_12 ")"
596 #define TOP_1 "(" TOP_11 "," TOP_12 ")"
597 #define BOT_1 "(" BOT_12 "," BOT_11 ")"
598 #define EDG_1 "(" EDG_11 "," BOT_12 ")"
600 #define ORG_2 "((LbnMarin,LbnzAlb4),LbnAlexa)"
602 #define BOT_2 "(LbnAlexa,(LbnMarin,LbnzAlb4))"
619 for (
int rotate = 0; rotate<=1; ++rotate) {
620 tree->reorder_tree(from_order);
621 if (rotate) tree->rotate_subtree();
622 tree->reorder_tree(to_order);
638 tree->rotate_subtree();
TEST_EXPECT_NEWICK(
nSIMPLE, tree,
"((LbnAlexa,(LbnzAlb4,LbnMarin)),((_MhuCaps,ThtNivea),((RsnAnta2,OnlGran2),((AticSea6,(RblMesop,RblAerol)),((PaoMaris,(MabSalin,MabPelag)),(MmbAlkal,(RsbElon4,DnrShiba)))))));");
650 "((" ORG_1112
"," TOP_1111
"),"
651 "((" ORG_2
"," TOP_12
")," ORG_112
"));");
655 tree->get_tree_root()->find_innermost_edge().set_root();
657 "((((LbnMarin:0.019,LbnzAlb4:0.003):0.016,LbnAlexa:0.032):0.122,(ThtNivea:0.230,_MhuCaps:0.194):0.427):0.076,"
658 "(((((DnrShiba:0.076,RsbElon4:0.053):0.034,MmbAlkal:0.069):0.016,((MabPelag:0.001,MabSalin:0.009):0.095,PaoMaris:0.092):0.036):0.030,((RblAerol:0.085,RblMesop:0.042):0.238,AticSea6:0.111):0.018):0.036,(OnlGran2:0.057,RsnAnta2:0.060):0.021):0.076);");
GB_ERROR GBK_system(const char *system_command)
size_t GBT_count_leafs(const TreeNode *tree)
GBDATA * GB_open(const char *path, const char *opent)
void put(const char *elem)
GB_ERROR GBT_write_tree_with_remark(GBDATA *gb_main, const char *tree_name, TreeNode *tree, const char *remark)
TreeNode * findLeafNamed(const char *wantedName)
int ARB_main(int argc, char *argv[])
char * get_tree_remark() const
#define TEST_STDOUT_CONTAINS(cmd, part)
char * ARB_strdup(const char *str)
const char * GBS_global_string(const char *templat,...)
char * ARB_strpartdup(const char *start, const char *end)
int GB_unlink(const char *path)
static GB_ERROR save_tree_as_newick(TreeNode *tree, const char *savename, const char *comment)
#define ARRAY_ELEMS(array)
#define DOWNCAST(totype, expr)
#define TEST_PUBLISH(testfunction)
GB_ERROR GB_await_error()
#define TEST_EXPECT(cond)
static int weight[maxsites+1]
void GB_warningf(const char *templat,...)
#define TEST_EXPECT_NEWICK(format, tree, expected_newick)
#define is_equal_to_NULL()
void add(SizeAwareTree *&tree, const char *treename, double weight)
#define TEST_REJECT(cond)
#define TEST_REJECT_NULL(n)
static void error(const char *msg)
TreeNode * TREE_load(const char *path, TreeRoot *troot, char **commentPtr, bool allow_length_scaling, char **warningPtr)
expectation_group & add(const expectation &e)
#define TEST_EXPECT_VALID_TREE(tree)
#define TEST_OUTPUT_CONTAINS(cmd, expected_std, expected_err)
#define TEST_EXPECT_ZERO_OR_SHOW_ERRNO(iocond)
#define TEST_EXPECT_TEXTFILE_DIFFLINES_IGNORE_DATES(fgot, fwant, diff)
GB_ERROR TREE_write_Newick(GBDATA *gb_main, const char *tree_name, const TreeLabeler &labeler, bool save_branchlengths, bool save_bootstraps, bool save_groupnames, bool pretty, LabelQuoting quoteMode, const char *path)
#define does_differ_from_NULL()
#define TEST_EXPECTATION(EXPCTN)
#define textfiles_have_difflines(f1, f2, ed)
#define textfiles_have_difflines_ignoreDates(f1, f2, ed)
#define TEST_EXPECT_NULL(n)
static list< LineAttachedMessage > warnings
#define fulfills(pred, arg)
SizeAwareTree * get(size_t &different_species, GB_ERROR &error)
#define TEST_EXPECT_NO_ERROR(call)
bool ARB_strBeginsWith(const char *str, const char *with)
GB_transaction ta(gb_var)
void destroy(TreeNode *that)
static char * create_tree_name(const char *savename)
#define TEST_EXPECT_EQUAL(expr, want)
static TreeNode * build_consensus_tree(const CharPtrArray &input_trees, GB_ERROR &error, size_t &different_species, double weight, char *&comment)
char * GBS_global_string_copy(const char *templat,...)
void GB_close(GBDATA *gbd)