Skip to content

Commit dd02b06

Browse files
committed
more
1 parent c84bcab commit dd02b06

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

examples/haploid_wright_fisher.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ fn stress_test_total_branch_length() {
163163
if let Some(tree) = tree_iter.next() {
164164
let b = tree.total_branch_length(false).unwrap();
165165
let b2 = unsafe {
166-
tskit::bindings::tsk_tree_get_total_branch_length(tree.as_ptr(), -1, &mut x)
166+
tskit::bindings::tsk_tree_get_total_branch_length(tree.as_ref(), -1, &mut x)
167167
};
168168
assert!(b2 >= 0, "{}", b2);
169169
assert!(f64::from(b) - x <= 1e-8);

src/sys/tree.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use super::bindings::tsk_size_t;
55
use super::bindings::tsk_tree_t;
66
use super::flags::TreeFlags;
77
use super::newtypes::NodeId;
8+
use super::newtypes::Position;
89
use super::newtypes::SizeType;
10+
use super::newtypes::Time;
911
use super::tskbox::TskBox;
1012
use super::TreeSequence;
1113
use super::TskitError;
@@ -205,6 +207,37 @@ impl<'treeseq> LLTree<'treeseq> {
205207
pub fn right_child_array(&self) -> &[NodeId] {
206208
super::generate_slice(self.as_ref().right_child, self.treeseq.num_nodes_raw() + 1)
207209
}
210+
211+
pub fn total_branch_length(&self, by_span: bool) -> Result<Time, TskitError> {
212+
let time: &[Time] = super::generate_slice(
213+
unsafe { (*(*(*self.as_ptr()).tree_sequence).tables).nodes.time },
214+
self.treeseq.num_nodes_raw() + 1,
215+
);
216+
let mut b = Time::from(0.);
217+
for n in self.traverse_nodes(NodeTraversalOrder::Preorder) {
218+
let p = self.parent(n).ok_or(TskitError::IndexError {})?;
219+
if p != NodeId::NULL {
220+
b += time[p.as_usize()] - time[n.as_usize()]
221+
}
222+
}
223+
224+
match by_span {
225+
true => Ok(b * self.span()),
226+
false => Ok(b),
227+
}
228+
}
229+
230+
pub fn interval(&self) -> (Position, Position) {
231+
(
232+
self.as_ref().interval.left.into(),
233+
self.as_ref().interval.right.into(),
234+
)
235+
}
236+
237+
pub fn span(&self) -> Position {
238+
let i = self.interval();
239+
i.1 - i.0
240+
}
208241
}
209242

210243
// Trait defining iteration over nodes.

src/trees/tree.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::sys::bindings as ll_bindings;
22
use crate::sys::{LLTree, TreeSequence};
33
use crate::NodeId;
4+
use crate::Time;
45
use crate::Position;
56
use crate::SizeType;
67
use crate::TreeFlags;
@@ -58,10 +59,20 @@ impl<'treeseq> Tree<'treeseq> {
5859

5960
/// Return the `[left, right)` coordinates of the tree.
6061
pub fn interval(&self) -> (Position, Position) {
61-
(
62-
self.inner.as_ref().interval.left.into(),
63-
self.inner.as_ref().interval.right.into(),
64-
)
62+
self.inner.interval()
63+
}
64+
65+
/// Calculate the total length of the tree via a preorder traversal.
66+
///
67+
/// # Parameters
68+
///
69+
/// * `by_span`: if `true`, multiply the return value by [`TreeInterface::span`].
70+
///
71+
/// # Errors
72+
///
73+
/// [`TskitError`] may be returned if a node index is out of range.
74+
pub fn total_branch_length(&self, by_span: bool) -> Result<Time, TskitError> {
75+
self.inner.total_branch_length(by_span)
6576
}
6677

6778
/// # Failing examples
@@ -154,6 +165,13 @@ impl<'treeseq> Tree<'treeseq> {
154165
self.inner.flags()
155166
}
156167

168+
/// Return the length of the genome for which this
169+
/// tree is the ancestry.
170+
pub fn span(&self) -> Position {
171+
let i = self.interval();
172+
i.1 - i.0
173+
}
174+
157175
/// Get the parent of node `u`.
158176
///
159177
/// Returns `None` if `u` is out of range.

0 commit comments

Comments
 (0)