Skip to content

Commit b9ee27d

Browse files
duncanMRmergify[bot]
authored andcommitted
Add tsk_tree_position_seek functions and revise seek_from_null
1 parent efad089 commit b9ee27d

File tree

3 files changed

+170
-14
lines changed

3 files changed

+170
-14
lines changed

c/tskit/trees.c

Lines changed: 167 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4567,6 +4567,136 @@ tsk_tree_position_step(tsk_tree_position_t *self, int direction)
45674567
return ret;
45684568
}
45694569

4570+
int TSK_WARN_UNUSED
4571+
tsk_tree_position_seek_forward(tsk_tree_position_t *self, tsk_id_t index)
4572+
{
4573+
int ret = 0;
4574+
const tsk_table_collection_t *tables = self->tree_sequence->tables;
4575+
const tsk_id_t M = (tsk_id_t) tables->edges.num_rows;
4576+
const tsk_id_t num_trees = (tsk_id_t) self->tree_sequence->num_trees;
4577+
const double *restrict left_coords = tables->edges.left;
4578+
const tsk_id_t *restrict left_order = tables->indexes.edge_insertion_order;
4579+
const double *restrict right_coords = tables->edges.right;
4580+
const tsk_id_t *restrict right_order = tables->indexes.edge_removal_order;
4581+
const double *restrict breakpoints = self->tree_sequence->breakpoints;
4582+
tsk_id_t j, left_current_index, right_current_index;
4583+
double left;
4584+
4585+
tsk_bug_assert(index >= self->index && index < num_trees);
4586+
4587+
if (self->index == -1) {
4588+
self->interval.right = 0;
4589+
self->in.stop = 0;
4590+
self->out.stop = 0;
4591+
self->direction = TSK_DIR_FORWARD;
4592+
}
4593+
4594+
if (self->direction == TSK_DIR_FORWARD) {
4595+
left_current_index = self->in.stop;
4596+
right_current_index = self->out.stop;
4597+
} else {
4598+
left_current_index = self->out.stop + 1;
4599+
right_current_index = self->in.stop + 1;
4600+
}
4601+
4602+
self->direction = TSK_DIR_FORWARD;
4603+
left = breakpoints[index];
4604+
4605+
j = right_current_index;
4606+
self->out.start = j;
4607+
while (j < M && right_coords[right_order[j]] <= left) {
4608+
j++;
4609+
}
4610+
self->out.stop = j;
4611+
4612+
if (self->index == -1) {
4613+
self->out.start = self->out.stop;
4614+
}
4615+
4616+
j = left_current_index;
4617+
while (j < M && right_coords[left_order[j]] <= left) {
4618+
j++;
4619+
}
4620+
self->in.start = j;
4621+
while (j < M && left_coords[left_order[j]] <= left) {
4622+
j++;
4623+
}
4624+
self->in.stop = j;
4625+
4626+
self->interval.left = left;
4627+
self->interval.right = breakpoints[index + 1];
4628+
self->out.order = right_order;
4629+
self->in.order = left_order;
4630+
self->index = index;
4631+
return ret;
4632+
}
4633+
4634+
int TSK_WARN_UNUSED
4635+
tsk_tree_position_seek_backward(tsk_tree_position_t *self, tsk_id_t index)
4636+
{
4637+
int ret = 0;
4638+
const tsk_table_collection_t *tables = self->tree_sequence->tables;
4639+
const tsk_id_t M = (tsk_id_t) tables->edges.num_rows;
4640+
const double sequence_length = tables->sequence_length;
4641+
const tsk_id_t num_trees = (tsk_id_t) self->tree_sequence->num_trees;
4642+
const double *restrict left_coords = tables->edges.left;
4643+
const tsk_id_t *restrict left_order = tables->indexes.edge_insertion_order;
4644+
const double *restrict right_coords = tables->edges.right;
4645+
const tsk_id_t *restrict right_order = tables->indexes.edge_removal_order;
4646+
const double *restrict breakpoints = self->tree_sequence->breakpoints;
4647+
tsk_id_t j, left_current_index, right_current_index;
4648+
double right;
4649+
4650+
if (self->index == -1) {
4651+
self->index = num_trees;
4652+
self->interval.left = sequence_length;
4653+
self->in.stop = M - 1;
4654+
self->out.stop = M - 1;
4655+
self->direction = TSK_DIR_REVERSE;
4656+
}
4657+
tsk_bug_assert(index <= self->index);
4658+
4659+
if (self->direction == TSK_DIR_REVERSE) {
4660+
left_current_index = self->out.stop;
4661+
right_current_index = self->in.stop;
4662+
} else {
4663+
left_current_index = self->in.stop - 1;
4664+
right_current_index = self->out.stop - 1;
4665+
}
4666+
4667+
self->direction = TSK_DIR_REVERSE;
4668+
right = breakpoints[index + 1];
4669+
4670+
j = left_current_index;
4671+
self->out.start = j;
4672+
while (j >= 0 && left_coords[left_order[j]] >= right) {
4673+
j--;
4674+
}
4675+
self->out.stop = j;
4676+
4677+
if (self->index == num_trees) {
4678+
self->out.start = self->out.stop;
4679+
}
4680+
4681+
j = right_current_index;
4682+
while (j >= 0 && left_coords[right_order[j]] >= right) {
4683+
j--;
4684+
}
4685+
self->in.start = j;
4686+
while (j >= 0 && right_coords[right_order[j]] >= right) {
4687+
j--;
4688+
}
4689+
self->in.stop = j;
4690+
4691+
self->interval.right = right;
4692+
self->interval.left = breakpoints[index];
4693+
self->out.order = left_order;
4694+
self->in.order = right_order;
4695+
self->index = index;
4696+
4697+
return ret;
4698+
}
4699+
45704700
/* ======================================================== *
45714701
* Tree
45724702
* ======================================================== */
@@ -5606,20 +5736,48 @@ static int
56065736
tsk_tree_seek_from_null(tsk_tree_t *self, double x, tsk_flags_t TSK_UNUSED(options))
56075737
{
56085738
int ret = 0;
5739+
tsk_table_collection_t *tables = self->tree_sequence->tables;
5740+
const tsk_id_t *restrict edge_parent = tables->edges.parent;
5741+
const tsk_id_t *restrict edge_child = tables->edges.child;
5742+
const double *restrict edge_left = tables->edges.left;
5743+
const double *restrict edge_right = tables->edges.right;
5744+
const double *restrict breakpoints = self->tree_sequence->breakpoints;
5745+
const tsk_size_t num_trees = self->tree_sequence->num_trees;
5746+
const double L = tsk_treeseq_get_sequence_length(self->tree_sequence);
5747+
tsk_id_t j, e, index;
56095748

5610-
tsk_bug_assert(self->index == -1);
5611-
5612-
ret = tsk_tree_next(self);
5613-
if (ret < 0) {
5614-
goto out;
5749+
index = (tsk_id_t) tsk_search_sorted(breakpoints, num_trees + 1, x);
5750+
if (breakpoints[index] > x) {
5751+
index--;
56155752
}
5616-
while (!tsk_tree_position_in_interval(self, x)) {
5617-
ret = tsk_tree_next(self);
5618-
if (ret < 0) {
5753+
5754+
if (x <= L / 2.0) {
5755+
ret = tsk_tree_position_seek_forward(&self->tree_pos, index);
5756+
if (ret != 0) {
5757+
goto out;
5758+
}
5759+
tsk_tree_update_index_and_interval(self);
5760+
for (j = self->tree_pos.in.start; j != self->tree_pos.in.stop; j++) {
5761+
e = self->tree_pos.in.order[j];
5762+
if (edge_left[e] <= self->interval.left
5763+
&& self->interval.left < edge_right[e]) {
5764+
tsk_tree_insert_edge(self, edge_parent[e], edge_child[e], e);
5765+
}
5766+
}
5767+
} else {
5768+
ret = tsk_tree_position_seek_backward(&self->tree_pos, index);
5769+
if (ret != 0) {
56195770
goto out;
56205771
}
5772+
tsk_tree_update_index_and_interval(self);
5773+
for (j = self->tree_pos.in.start; j != self->tree_pos.in.stop; j--) {
5774+
e = self->tree_pos.in.order[j];
5775+
if (edge_right[e] >= self->interval.right
5776+
&& self->interval.right > edge_left[e]) {
5777+
tsk_tree_insert_edge(self, edge_parent[e], edge_child[e], e);
5778+
}
5779+
}
56215780
}
5622-
ret = 0;
56235781
out:
56245782
return ret;
56255783
}

c/tskit/trees.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,7 @@ bool tsk_tree_position_prev(tsk_tree_position_t *self);
18531853
bool tsk_tree_position_step(tsk_tree_position_t *self, int direction);
18541854
int tsk_tree_position_seek_forward(tsk_tree_position_t *self, tsk_id_t index);
18551855
int tsk_tree_position_seek_backward(tsk_tree_position_t *self, tsk_id_t index);
1856+
int tsk_tree_position_seek(tsk_tree_position_t *self, double position);
18561857

18571858
#ifdef __cplusplus
18581859
}

python/tests/test_highlevel.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4645,8 +4645,7 @@ def test_index_from_different_directions(self, index):
46454645
t2.prev()
46464646
assert_same_tree_different_order(t1, t2)
46474647

4648-
@pytest.mark.skip("Fails due to temporary seek_from_null implementation")
4649-
# @pytest.mark.parametrize("position", [0, 1, 2, 3])
4648+
@pytest.mark.parametrize("position", [0, 1, 2, 3])
46504649
def test_seek_from_null(self, position):
46514650
t1, t2 = self.get_tree_pair()
46524651
t1.clear()
@@ -4699,7 +4698,6 @@ def test_seek_1_5_from_1(self):
46994698
t2.seek(1.5)
47004699
assert_trees_identical(t1, t2)
47014700

4702-
@pytest.mark.skip("Fails due to temporary seek_from_null implementation")
47034701
def test_seek_3_from_null(self):
47044702
t1, t2 = self.get_tree_pair()
47054703
t1.last()
@@ -4748,8 +4746,7 @@ def test_seek_mid_null_and_middle(self, ts):
47484746
assert t1.index == t2.index
47494747
assert np.all(t1.parent_array == t2.parent_array)
47504748

4751-
@pytest.mark.skip("Fails due to temporary seek_from_null implementation")
4752-
# @pytest.mark.parametrize("ts", get_example_tree_sequences())
4749+
@pytest.mark.parametrize("ts", get_example_tree_sequences())
47534750
def test_seek_last_then_prev(self, ts):
47544751
t1 = tskit.Tree(ts)
47554752
t1.seek(ts.sequence_length - 0.00001)

0 commit comments

Comments
 (0)