obj rs_save_image_file( obj root, obj ref_vec, obj ref_names, obj rplc, obj out_info ) { int i; obj *save, result, output_id; char *outfile_name = NULL; FILE *outfile_strm = NULL; /* Phase 1 --- Setup */ if (STRING_P(out_info)) { outfile_name = string_text(out_info); outfile_strm = fopen( outfile_name, "wb" ); if (!outfile_strm) { scheme_error( "~a: error opening image output", 1, out_info ); } } for (i=0; i<NUM_CLASS_MODES; i++) hi_init_queue( &image_modes[i].queue ); hi_init_queue( &used_refs ); if (OBJ_ISA_PTR(rplc)) setup_replacement_objects( rplc ); save = setup_reference_objects( ref_vec ); /* Phase 2 --- Traversal */ spot_object( root ); traverse_all(); /* Phase 3 --- Name Assignment */ output_id = OBJ(POINTER_TAG); output_id = assign_ref_queue_names( &used_refs, output_id ); for (i=0; i<NUM_CLASS_MODES; i++) output_id = assign_queue_names( &image_modes[i].queue, output_id ); #if DEBUG_SAVE printf( "%u objects named in output\n", VAL(output_id)>>PRIMARY_TAG_SIZE ); #endif /* Phase 4 --- Output */ if (outfile_strm) { #if DEBUG_SAVE printf( "writing image to file: \"%s\"\n", outfile_name ); #endif do_file_output( outfile_strm, ref_vec, ref_names, root ); } /* Phase 5 --- Cleanup */ for (i=0; i<NUM_CLASS_MODES; i++) cleanup_queued_objects( &image_modes[i].queue ); cleanup_reference_objects( ref_vec, save ); cleanup_queued_objects( &rplc_queue ); if (EQ(out_info,TRUE_OBJ)) result = do_vector_output(); else result = TRUE_OBJ; for (i=0; i<NUM_CLASS_MODES; i++) hi_free_queue( &image_modes[i].queue ); clear_part_descr_labels( &used_refs ); hi_free_queue( &used_refs ); return result; }
int neighbor_joining(matrix *distance, tree_s *out_tree) { size_t matrix_size = distance->size; if (matrix_size < 3 || !out_tree) return -2; int check; check = tree_init(out_tree, matrix_size); if (check) return check; tree_node *node_pool = out_tree->pool; tree_node *empty_node_ptr = &node_pool[matrix_size]; tree_node **unjoined_nodes = malloc(matrix_size * sizeof(tree_node *)); CHECK_MALLOC(unjoined_nodes); size_t n = matrix_size; size_t i, j; for (i = 0; i < n; i++) { node_pool[i] = LEAF(i); unjoined_nodes[i] = &node_pool[i]; } double r[matrix_size]; matrix local_copy; check = matrix_copy(&local_copy, distance); assert(check == 0); assert(local_copy.size == distance->size); assert(memcmp(local_copy.data, distance->data, matrix_size * matrix_size * sizeof(double)) == 0); #define M(I, J) (MATRIX_CELL(local_copy, I, J)) while (n > 3) { for (i = 0; i < n; i++) { double rr = 0.0; for (j = 0; j < n; j++) { if (i == j) assert(M(i, j) == 0.0); assert(M(i, j) == M(j, i)); rr += M(i, j); } r[i] = rr / (double)(n - 2); } size_t min_i = 0, min_j = 1; double min_value = M(0, 1) - r[0] - r[1]; for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { if (i == j) continue; double value = M(i, j) - r[i] - r[j]; if (value < min_value) { min_i = i; min_j = j; min_value = value; } } } // force i < j if (min_j < min_i) { size_t temp = min_i; min_i = min_j; min_j = temp; } tree_node branch = { .left_branch = unjoined_nodes[min_i], .right_branch = unjoined_nodes[min_j], .left_dist = (M(min_i, min_j) + r[min_i] - r[min_j]) / 2.0, .right_dist = (M(min_i, min_j) - r[min_i] + r[min_j]) / 2.0, .index = -1}; *empty_node_ptr++ = branch; unjoined_nodes[min_i] = empty_node_ptr - 1; unjoined_nodes[min_j] = unjoined_nodes[n - 1]; double row_k[matrix_size]; double M_ij = M(min_i, min_j); for (size_t m = 0; m < n; m++) { if (m == min_i || m == min_j) continue; row_k[m] = (M(min_i, m) + M(min_j, m) - M_ij) / 2.0; // if( row_k[m] < 0) row_k[m] = 0; } // row_k[min_i] and row_k[min_j] are undefined! row_k[min_i] = 0.0; row_k[min_j] = row_k[n - 1]; memmove(&M(min_i, 0), row_k, matrix_size * sizeof(double)); memmove(&M(min_j, 0), &M((n - 1), 0), matrix_size * sizeof(double)); M(min_i, min_i) = M(min_j, min_j) = 0.0; for (i = 0; i < n; i++) { M(i, min_i) = M(min_i, i); } for (i = 0; i < n; i++) { M(i, min_j) = M(min_j, i); } n--; } // join three remaining nodes tree_root root = {.left_branch = unjoined_nodes[0], .right_branch = unjoined_nodes[1], .extra_branch = unjoined_nodes[2], .left_dist = (M(0, 1) + M(0, 2) - M(1, 2)) / 2.0, .right_dist = (M(0, 1) + M(1, 2) - M(0, 2)) / 2.0, .extra_dist = (M(0, 2) + M(1, 2) - M(0, 1)) / 2.0}; //*empty_node_ptr++ = root; out_tree->root = root; free(unjoined_nodes); matrix_free(&local_copy); return 0; } void traverse_all(tree_node *current, visitor_ctx *v, void *context) { if (v->pre) { v->pre(current, context); } if (current->left_branch) { traverse_all(current->left_branch, v, context); } if (v->process) { v->process(current, context); } if (current->right_branch) { traverse_all(current->right_branch, v, context); } if (v->post) { v->post(current, context); } } void newick_sv_pre(tree_node *current, void *ctx) { if (current->left_branch) { printf("("); } } void newick_sv_process(tree_node *current, void *ctx) { if (current->left_branch) { if (current->left_branch->left_branch) { printf("%d:%lf,", (int)(current->left_support * 100), current->left_dist); } else { printf(":%lf,", current->left_dist); } } else { printf("%s", ((char **)ctx)[current->index]); } } void newick_sv_post(tree_node *current, void *ctx) { if (!current->right_branch) return; if (current->right_branch->right_branch) { printf("%d:%lf)", (int)(current->right_support * 100), current->right_dist); } else { printf(":%lf)", current->right_dist); } } void newick_sv(tree_root *root, char **names) { visitor_ctx v = {.pre = newick_sv_pre, .process = newick_sv_process, .post = newick_sv_post}; printf("("); traverse_all(root->left_branch, &v, names); newick_sv_process(&root->as_tree_node, names); traverse_all(root->right_branch, &v, names); if (root->right_branch && root->right_branch->right_branch) { printf("%d:%lf,", (int)(root->right_support * 100), root->right_dist); } else { printf(":%lf,", root->right_dist); } traverse_all(root->extra_branch, &v, names); if (root->extra_branch && root->extra_branch->left_branch) { printf("%d:%lf)", (int)(root->extra_support * 100), root->extra_dist); } else { printf(":%lf)", root->extra_dist); } printf(";\n"); }