Skip to content

Commit 2391c9e

Browse files
authored
Add support for virtual roots (#205)
* add Tree::virtual_root * add 1 to the length of each array defining the tree structure * RootIterator now uses virtual_root. * Update PreorderNodeIterator to use virtual_root * Add Tree::array_len to account for array lengths with virtual roots. Closes #170
1 parent 4cf3496 commit 2391c9e

File tree

1 file changed

+32
-36
lines changed

1 file changed

+32
-36
lines changed

src/trees.rs

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct Tree {
3131
current_tree: i32,
3232
advanced: bool,
3333
num_nodes: tsk_size_t,
34+
array_len: tsk_size_t,
3435
flags: TreeFlags,
3536
}
3637

@@ -58,6 +59,7 @@ impl Tree {
5859
current_tree: 0,
5960
advanced: false,
6061
num_nodes,
62+
array_len: num_nodes + 1,
6163
flags,
6264
}
6365
}
@@ -100,7 +102,7 @@ impl Tree {
100102
/// }
101103
/// ```
102104
pub fn parent_array(&self) -> &[NodeId] {
103-
tree_array_slice!(self, parent, (*self.inner).num_nodes)
105+
tree_array_slice!(self, parent, self.array_len)
104106
}
105107

106108
/// # Failing examples
@@ -267,7 +269,7 @@ impl Tree {
267269
/// }
268270
/// ```
269271
pub fn left_sib_array(&self) -> &[NodeId] {
270-
tree_array_slice!(self, left_sib, (*self.inner).num_nodes)
272+
tree_array_slice!(self, left_sib, self.array_len)
271273
}
272274

273275
/// # Failing examples
@@ -287,7 +289,7 @@ impl Tree {
287289
/// }
288290
/// ```
289291
pub fn right_sib_array(&self) -> &[NodeId] {
290-
tree_array_slice!(self, right_sib, (*self.inner).num_nodes)
292+
tree_array_slice!(self, right_sib, self.array_len)
291293
}
292294

293295
/// # Failing examples
@@ -307,7 +309,7 @@ impl Tree {
307309
/// }
308310
/// ```
309311
pub fn left_child_array(&self) -> &[NodeId] {
310-
tree_array_slice!(self, left_child, (*self.inner).num_nodes)
312+
tree_array_slice!(self, left_child, self.array_len)
311313
}
312314

313315
/// # Failing examples
@@ -327,7 +329,7 @@ impl Tree {
327329
/// }
328330
/// ```
329331
pub fn right_child_array(&self) -> &[NodeId] {
330-
tree_array_slice!(self, right_child, (*self.inner).num_nodes)
332+
tree_array_slice!(self, right_child, self.array_len)
331333
}
332334

333335
fn left_sample(&self, u: NodeId) -> Result<NodeId, TskitError> {
@@ -367,7 +369,7 @@ impl Tree {
367369
///
368370
/// [`TskitError`] if `u` is out of range.
369371
pub fn parent(&self, u: NodeId) -> Result<NodeId, TskitError> {
370-
unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).parent, NodeId)
372+
unsafe_tsk_column_access!(u.0, 0, self.array_len, (*self.inner).parent, NodeId)
371373
}
372374

373375
/// Get the left child of node `u`.
@@ -376,7 +378,7 @@ impl Tree {
376378
///
377379
/// [`TskitError`] if `u` is out of range.
378380
pub fn left_child(&self, u: NodeId) -> Result<NodeId, TskitError> {
379-
unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).left_child, NodeId)
381+
unsafe_tsk_column_access!(u.0, 0, self.array_len, (*self.inner).left_child, NodeId)
380382
}
381383

382384
/// Get the right child of node `u`.
@@ -385,7 +387,7 @@ impl Tree {
385387
///
386388
/// [`TskitError`] if `u` is out of range.
387389
pub fn right_child(&self, u: NodeId) -> Result<NodeId, TskitError> {
388-
unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).right_child, NodeId)
390+
unsafe_tsk_column_access!(u.0, 0, self.array_len, (*self.inner).right_child, NodeId)
389391
}
390392

391393
/// Get the left sib of node `u`.
@@ -394,7 +396,7 @@ impl Tree {
394396
///
395397
/// [`TskitError`] if `u` is out of range.
396398
pub fn left_sib(&self, u: NodeId) -> Result<NodeId, TskitError> {
397-
unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).left_sib, NodeId)
399+
unsafe_tsk_column_access!(u.0, 0, self.array_len, (*self.inner).left_sib, NodeId)
398400
}
399401

400402
/// Get the right sib of node `u`.
@@ -403,7 +405,7 @@ impl Tree {
403405
///
404406
/// [`TskitError::IndexError`] if `u` is out of range.
405407
pub fn right_sib(&self, u: NodeId) -> Result<NodeId, TskitError> {
406-
unsafe_tsk_column_access!(u.0, 0, self.num_nodes, (*self.inner).right_sib, NodeId)
408+
unsafe_tsk_column_access!(u.0, 0, self.array_len, (*self.inner).right_sib, NodeId)
407409
}
408410

409411
/// Obtain the list of samples for the current tree/tree sequence
@@ -577,6 +579,11 @@ impl Tree {
577579
};
578580
handle_tsk_return_value!(code, kc)
579581
}
582+
583+
/// Return the virtual root of the tree.
584+
pub fn virtual_root(&self) -> NodeId {
585+
(*self.inner).virtual_root.into()
586+
}
580587
}
581588

582589
impl streaming_iterator::StreamingIterator for Tree {
@@ -639,7 +646,7 @@ pub enum NodeTraversalOrder {
639646
}
640647

641648
struct PreorderNodeIterator<'a> {
642-
root_stack: Vec<NodeId>,
649+
current_root: NodeId,
643650
node_stack: Vec<NodeId>,
644651
tree: &'a Tree,
645652
current_node_: Option<NodeId>,
@@ -648,14 +655,15 @@ struct PreorderNodeIterator<'a> {
648655
impl<'a> PreorderNodeIterator<'a> {
649656
fn new(tree: &'a Tree) -> Self {
650657
let mut rv = PreorderNodeIterator {
651-
root_stack: tree.roots_to_vec(),
658+
current_root: tree.right_child(tree.virtual_root()).unwrap(),
652659
node_stack: vec![],
653660
tree,
654661
current_node_: None,
655662
};
656-
rv.root_stack.reverse();
657-
if let Some(root) = rv.root_stack.pop() {
658-
rv.node_stack.push(root);
663+
let mut c = rv.current_root;
664+
while !c.is_null() {
665+
rv.node_stack.push(c);
666+
c = rv.tree.left_sib(c).unwrap();
659667
}
660668
rv
661669
}
@@ -664,26 +672,14 @@ impl<'a> PreorderNodeIterator<'a> {
664672
impl NodeIterator for PreorderNodeIterator<'_> {
665673
fn next_node(&mut self) {
666674
self.current_node_ = self.node_stack.pop();
667-
match self.current_node_ {
668-
Some(u) => {
669-
// NOTE: process children right-to-left
670-
// because we later pop them from a steck
671-
// to generate the expected left-to-right ordering.
672-
let mut c = self.tree.right_child(u).unwrap();
673-
while c != NodeId::NULL {
674-
self.node_stack.push(c);
675-
c = self.tree.left_sib(c).unwrap();
676-
}
677-
}
678-
None => {
679-
if let Some(r) = self.root_stack.pop() {
680-
self.current_node_ = Some(r);
681-
let mut c = self.tree.right_child(r).unwrap();
682-
while c != NodeId::NULL {
683-
self.node_stack.push(c);
684-
c = self.tree.left_sib(c).unwrap();
685-
}
686-
}
675+
if let Some(u) = self.current_node_ {
676+
// NOTE: process children right-to-left
677+
// because we later pop them from a steck
678+
// to generate the expected left-to-right ordering.
679+
let mut c = self.tree.right_child(u).unwrap();
680+
while c != NodeId::NULL {
681+
self.node_stack.push(c);
682+
c = self.tree.left_sib(c).unwrap();
687683
}
688684
};
689685
}
@@ -763,7 +759,7 @@ impl<'a> RootIterator<'a> {
763759
fn new(tree: &'a Tree) -> Self {
764760
RootIterator {
765761
current_root: None,
766-
next_root: unsafe { ll_bindings::tsk_tree_get_left_root(tree.as_ptr()).into() },
762+
next_root: tree.left_child(tree.virtual_root()).unwrap(),
767763
tree,
768764
}
769765
}

0 commit comments

Comments
 (0)