1 | #include <TreeRead.h> |
---|
2 | #include <time.h> |
---|
3 | |
---|
4 | // add_bootstrap interprets the length of the branches as bootstrap value |
---|
5 | // (this is needed by Phylip DNAPARS/PROTPARS with bootstrapping) |
---|
6 | // |
---|
7 | // 'hundred' specifies which value represents 100% |
---|
8 | |
---|
9 | void add_bootstrap(GBT_TREE *node, double hundred) { |
---|
10 | if (node->is_leaf) { |
---|
11 | freeset(node->remark_branch, 0); |
---|
12 | return; |
---|
13 | } |
---|
14 | |
---|
15 | node->leftlen /= hundred; |
---|
16 | node->rightlen /= hundred; |
---|
17 | |
---|
18 | double left_bs = node->leftlen * 100.0 + 0.5; |
---|
19 | double right_bs = node->rightlen * 100.0 + 0.5; |
---|
20 | |
---|
21 | #if defined(DEBUG) && 0 |
---|
22 | fprintf(stderr, "node->leftlen = %f left_bs = %f\n", node->leftlen, left_bs); |
---|
23 | fprintf(stderr, "node->rightlen = %f right_bs = %f\n", node->rightlen, right_bs); |
---|
24 | #endif // DEBUG |
---|
25 | |
---|
26 | node->leftson->remark_branch = GBS_global_string_copy("%2.0f%%", left_bs); |
---|
27 | node->rightson->remark_branch = GBS_global_string_copy("%2.0f%%", right_bs); |
---|
28 | |
---|
29 | node->leftlen = 0.1; // reset branchlengths |
---|
30 | node->rightlen = 0.1; |
---|
31 | |
---|
32 | add_bootstrap(node->leftson, hundred); |
---|
33 | add_bootstrap(node->rightson, hundred); |
---|
34 | } |
---|
35 | |
---|
36 | ATTRIBUTED(__ATTR__NORETURN, static void abort_with_usage(GBDATA *gb_main, const char *error)) { |
---|
37 | printf("Usage: arb_read_tree [-scale factor] [-consense #ofTrees] tree_name treefile [comment] [-commentFromFile file]\n"); |
---|
38 | if (error) { |
---|
39 | printf("Error: %s\n", error); |
---|
40 | GBT_message(gb_main, GBS_global_string("Error running arb_read_tree (%s)", error)); |
---|
41 | } |
---|
42 | exit(-1); |
---|
43 | } |
---|
44 | |
---|
45 | int main(int argc,char **argv) |
---|
46 | { |
---|
47 | GBDATA *gb_main = GB_open(":","r"); |
---|
48 | if (!gb_main){ |
---|
49 | printf("arb_read_tree: Error: you have to start an arbdb server first\n"); |
---|
50 | return -1; |
---|
51 | } |
---|
52 | |
---|
53 | #define SHIFT_ARGS(off) do { argc -= off; argv += off; } while(0) |
---|
54 | |
---|
55 | SHIFT_ARGS(1); // position onto first argument |
---|
56 | |
---|
57 | bool scale = false; |
---|
58 | double scale_factor = 0.0; |
---|
59 | |
---|
60 | if (argc>0 && strcmp("-scale",argv[0]) == 0) { |
---|
61 | scale = true; |
---|
62 | if (argc<2) abort_with_usage(gb_main, "-scale expects a 2nd argument (scale factor)"); |
---|
63 | scale_factor = atof(argv[1]); |
---|
64 | SHIFT_ARGS(2); |
---|
65 | } |
---|
66 | |
---|
67 | bool consense = false; |
---|
68 | int calculated_trees = 0; |
---|
69 | |
---|
70 | if (argc>0 && strcmp("-consense",argv[0]) == 0) { |
---|
71 | consense = true; |
---|
72 | if (argc<2) abort_with_usage(gb_main, "-consense expects a 2nd argument (number of trees)"); |
---|
73 | |
---|
74 | calculated_trees = atoi(argv[1]); |
---|
75 | if (calculated_trees < 1) { |
---|
76 | abort_with_usage(gb_main, GBS_global_string("Illegal # of trees (%i) for -consense", calculated_trees)); |
---|
77 | } |
---|
78 | |
---|
79 | SHIFT_ARGS(2); |
---|
80 | } |
---|
81 | |
---|
82 | if (!argc) abort_with_usage(gb_main, "Missing argument 'tree_name'"); |
---|
83 | const char *tree_name = argv[0]; |
---|
84 | SHIFT_ARGS(1); |
---|
85 | |
---|
86 | if (!argc) abort_with_usage(gb_main, "Missing argument 'treefile'"); |
---|
87 | const char *filename = argv[0]; |
---|
88 | SHIFT_ARGS(1); |
---|
89 | |
---|
90 | const char *comment = 0; |
---|
91 | if (argc>0) { |
---|
92 | comment = argv[0]; |
---|
93 | SHIFT_ARGS(1); |
---|
94 | } |
---|
95 | |
---|
96 | const char *commentFile = 0; |
---|
97 | if (argc>0 && strcmp("-commentFromFile", argv[0]) == 0) { |
---|
98 | if (argc<2) abort_with_usage(gb_main, "-commentFromFile expects a 2nd argument (file containing comment)"); |
---|
99 | commentFile = argv[1]; |
---|
100 | SHIFT_ARGS(2); |
---|
101 | } |
---|
102 | |
---|
103 | // end of argument parsing! |
---|
104 | if (argc>0) abort_with_usage(gb_main, GBS_global_string("unexpected argument(s): %s ..", argv[0])); |
---|
105 | |
---|
106 | // -------------------------------------------------------------------------------- |
---|
107 | |
---|
108 | char *comment_from_file = 0; |
---|
109 | if (commentFile) { |
---|
110 | comment_from_file = GB_read_file(commentFile); |
---|
111 | if (!comment_from_file) { |
---|
112 | comment_from_file = GBS_global_string_copy("Error reading from comment-file '%s':\n%s", commentFile, GB_await_error()); |
---|
113 | } |
---|
114 | } |
---|
115 | |
---|
116 | char *comment_from_treefile = 0; |
---|
117 | GBT_message(gb_main, GBS_global_string("Reading tree from '%s' ..", filename)); |
---|
118 | |
---|
119 | GB_ERROR error = 0; |
---|
120 | GBT_TREE *tree; |
---|
121 | { |
---|
122 | char *scaleWarning = 0; |
---|
123 | |
---|
124 | tree = TREE_load(filename, sizeof(GBT_TREE), &comment_from_treefile, (consense||scale) ? 0 : 1, &scaleWarning); |
---|
125 | if (!tree) { |
---|
126 | error = GB_await_error(); |
---|
127 | } |
---|
128 | else { |
---|
129 | if (scaleWarning) { |
---|
130 | GBT_message(gb_main, scaleWarning); |
---|
131 | free(scaleWarning); |
---|
132 | } |
---|
133 | } |
---|
134 | } |
---|
135 | |
---|
136 | if (!error) { |
---|
137 | if (scale) { |
---|
138 | GBT_message(gb_main, GBS_global_string("Scaling branch lengths by factor %f.", scale_factor)); |
---|
139 | TREE_scale(tree, scale_factor, 1.0); |
---|
140 | } |
---|
141 | |
---|
142 | if (consense) { |
---|
143 | if (calculated_trees < 1) { |
---|
144 | error = "Minimum for -consense is 1"; |
---|
145 | } |
---|
146 | else { |
---|
147 | GBT_message(gb_main, GBS_global_string("Reinterpreting branch lengths as consense values (%i trees).", calculated_trees)); |
---|
148 | add_bootstrap(tree, calculated_trees); |
---|
149 | } |
---|
150 | } |
---|
151 | } |
---|
152 | |
---|
153 | if (!error) { |
---|
154 | error = GB_begin_transaction(gb_main); |
---|
155 | |
---|
156 | if (!error && tree->is_leaf) error = "Cannot load tree (need at least 2 leafs)"; |
---|
157 | if (!error) error = GBT_write_tree(gb_main,0,tree_name,tree); |
---|
158 | |
---|
159 | if (!error) { |
---|
160 | // write tree comment: |
---|
161 | const char *datestring; |
---|
162 | { |
---|
163 | time_t date; |
---|
164 | if (time(&date) == -1) datestring = "<Error calculating time>"; |
---|
165 | else datestring = ctime(&date); |
---|
166 | } |
---|
167 | |
---|
168 | char *load_info = GBS_global_string_copy("Tree loaded from '%s' on %s", filename, datestring); |
---|
169 | |
---|
170 | #define COMMENT_SOURCES 4 |
---|
171 | const char *comments[COMMENT_SOURCES] = { |
---|
172 | comment, |
---|
173 | comment_from_file, |
---|
174 | comment_from_treefile, |
---|
175 | load_info, |
---|
176 | }; |
---|
177 | |
---|
178 | GBS_strstruct *buf = GBS_stropen(5000); |
---|
179 | bool empty = true; |
---|
180 | |
---|
181 | for (int c = 0; c<COMMENT_SOURCES; c++) { |
---|
182 | if (comments[c]) { |
---|
183 | if (!empty) GBS_chrcat(buf, '\n'); |
---|
184 | GBS_strcat(buf, comments[c]); |
---|
185 | empty = false; |
---|
186 | } |
---|
187 | } |
---|
188 | |
---|
189 | char *cmt = GBS_strclose(buf); |
---|
190 | |
---|
191 | error = GBT_write_tree_rem(gb_main, tree_name, cmt); |
---|
192 | |
---|
193 | free(cmt); |
---|
194 | free(load_info); |
---|
195 | } |
---|
196 | |
---|
197 | error = GB_end_transaction(gb_main, error); |
---|
198 | } |
---|
199 | |
---|
200 | if (error) GBT_message(gb_main, error); |
---|
201 | else GBT_message(gb_main, GBS_global_string("Tree %s read into the database", tree_name)); |
---|
202 | |
---|
203 | GB_close(gb_main); |
---|
204 | |
---|
205 | free(comment_from_file); |
---|
206 | free(comment_from_treefile); |
---|
207 | |
---|
208 | return error ? EXIT_FAILURE : EXIT_SUCCESS; |
---|
209 | } |
---|