aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-04-28 16:32:06 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-04-28 16:32:06 -0700
commita48e7f9fd525b4da828605fb7be4d2a35dde4e23 (patch)
tree51b7def97deeaa70c8003225fabd2bb62a1101f4 /sys
parenta6d9c8be245ef171423ddeb8466a27ad715012e0 (diff)
feat: prototype of rerooting function
Diffstat (limited to 'sys')
-rw-r--r--sys/libbio/io/newick.c6
-rw-r--r--sys/libbio/phylo.c59
-rw-r--r--sys/libbio/test.c17
3 files changed, 71 insertions, 11 deletions
diff --git a/sys/libbio/io/newick.c b/sys/libbio/io/newick.c
index cc6d3ff..038b41c 100644
--- a/sys/libbio/io/newick.c
+++ b/sys/libbio/io/newick.c
@@ -329,7 +329,7 @@ ERROR:
}
error
-bio·readnewick(io·Peeker stream, void *s, mem·Allocator heap, void *h, bio·Tree *tree)
+bio·readnewick(io·Peeker stream, void *s, bio·Tree *tree)
{
error err;
struct Parser p;
@@ -350,8 +350,8 @@ bio·readnewick(io·Peeker stream, void *s, mem·Allocator heap, void *h, bio·T
.tok = (struct Token){ 0 },
.fimpl = s,
.file = stream,
- .himpl = h,
- .heap = heap,
+ .himpl = tree->h,
+ .heap = tree->heap,
};
err = parse(&p);
if (err) {
diff --git a/sys/libbio/phylo.c b/sys/libbio/phylo.c
index 316537c..4a4bcb1 100644
--- a/sys/libbio/phylo.c
+++ b/sys/libbio/phylo.c
@@ -146,3 +146,62 @@ phylo·ladderize(bio·Node *root)
return 0;
}
+
+static
+error
+rotateparent(bio·Node *node, bio·Node *to)
+{
+ error err;
+ bio·Node *it, *prev;
+
+ if (node->parent == to) {
+ return 0;
+ }
+
+ prev = nil;
+ for (it = node->child; it != nil; it = it->sibling) {
+ if (it == to) goto FOUND;
+ prev = it;
+ }
+ errorf("inconsistent topology: attempting to rotate to non-child");
+ return 1;
+
+FOUND:
+ if (err = rotateparent(node->parent, node), err) {
+ errorf("failure: broken tree");
+ return err;
+ }
+
+ if (!prev) {
+ node->child = node->parent;
+ } else {
+ prev->sibling = node->parent;
+ }
+ node->parent->sibling = it->sibling;
+ node->parent = to;
+
+ return 0;
+}
+
+#define FLOAT_PREC .00000001
+error
+phylo·reroot(bio·Tree *tree, bio·Node *node, double d)
+{
+ bio·Node *old;
+ bio·Node *new;
+
+ // TODO: should check that node is part of this tree?
+
+ old = tree->root;
+ if (fabs(d) < FLOAT_PREC) new = node;
+ if (fabs(d-node->dist) < FLOAT_PREC) new = node->parent;
+ else {
+ new = tree->heap.alloc(tree->h, 1, sizeof(*new));
+ memset(new, 0, sizeof(*new));
+ }
+
+ // TODO: Use rotateparent() to perform necessary flips
+
+ tree->root = new;
+ return 0;
+}
diff --git a/sys/libbio/test.c b/sys/libbio/test.c
index baccd42..5059ce6 100644
--- a/sys/libbio/test.c
+++ b/sys/libbio/test.c
@@ -93,22 +93,23 @@ test·newick()
{
error err;
bio·Tree t;
- mem·Arena *mem;
+ mem·Arena *heap;
Stream *fd[2];
io·Peeker rdr;
io·Putter wtr;
- mem·Allocator al;
- mem = mem·newarena(mem·sys, nil);
- rdr = (io·Peeker){.get = &io·getbyte, .unget = &io·ungetbyte};
- wtr = (io·Putter){.put = &io·putbyte, .putstr = &io·putstring};
- al = (mem·Allocator) { .alloc = &mem·arenaalloc, .free = nil, };
+ heap = mem·newarena(mem·sys, nil);
+ rdr = (io·Peeker){.get = &io·getbyte, .unget = &io·ungetbyte};
+ wtr = (io·Putter){.put = &io·putbyte, .putstr = &io·putstring};
fd[0] = io·open("/home/nolln/root/data/test/zika.nwk", "r");
fd[1] = io·open("/home/nolln/root/data/test/zika.proc.nwk", "w");
- err = bio·readnewick(rdr, fd[0], al, mem, &t);
+ t.h = heap;
+ t.heap = (mem·Allocator){ .alloc = &mem·arenaalloc, .free = nil, };
+
+ err = bio·readnewick(rdr, fd[0], &t);
phylo·ladderize(t.root);
printf("Loaded tree with %d leafs and %d nodes\n", t.nleaf, t.root->nnode);
@@ -119,7 +120,7 @@ test·newick()
io·close(fd[0]);
io·close(fd[1]);
- mem·freearena(mem);
+ mem·freearena(heap);
return 0;
}