Skip to content

Commit 734b6cd

Browse files
authored
doc: add book sections on table data access (#379)
1 parent 44c0f96 commit 734b6cd

File tree

4 files changed

+100
-0
lines changed

4 files changed

+100
-0
lines changed

book/src/SUMMARY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@
44
- [Working with table collections](./working_with_table_collections.md)
55
- [Creation](./table_collection_creation.md)
66
- [Adding rows](./table_collection_adding_rows.md)
7+
- [Accessing table columns](./table_collection_column_access.md)
8+
- [Accessing table rows](./table_collection_row_access.md)
79
- [Validating table collection contents](./table_collection_validation.md)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## Accessing table columns
2+
3+
We can access table rows using either the relevant newtype or `i32` (which is identical to the `tskit-c` typedef `tsk_id_t`).
4+
The following snippet adds and edge and then validates the data for that row of the table:
5+
6+
```rust, noplaygound, ignore
7+
{{#include ../../tests/book_table_collection.rs:get_edge_table_columns}}
8+
```
9+
10+
The return type of the getters is the [`Option`](https://doc.rust-lang.org/std/option/enum.Option.html) enum. The `None` variant is returned when row indexes are out of range:
11+
12+
```rust, noplaygound, ignore
13+
{{#include ../../tests/book_table_collection.rs:get_edge_table_columns_out_of_range}}
14+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
## Accessing table rows
2+
3+
We may also access entire table rows by a row id:
4+
5+
```rust, noplaygound, ignore
6+
{{#include ../../tests/book_table_collection.rs:get_edge_table_row_by_id}}
7+
```
8+
9+
The row types are rust structures. The table data are *copied* into these structures, making them relatively more expensive to work with. We are looking into removing the copies and returning slices, but doing so currently impacts the design of table row iterators such as:
10+
11+
```rust, noplaygound, ignore
12+
{{#include ../../tests/book_table_collection.rs:get_edge_table_rows_by_iterator}}
13+
```
14+
15+
These iterators are rust iterator types--they `impl Iterator<Item=X>`, where `X` is a table row type.

tests/book_table_collection.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,72 @@ fn add_node_handle_error() {
6666
.check_integrity(tskit::TableIntegrityCheckFlags::default())
6767
.is_err());
6868
}
69+
70+
#[test]
71+
fn get_data_from_edge_table() {
72+
use rand::distributions::Distribution;
73+
let sequence_length = tskit::Position::from(100.0);
74+
let mut rng = rand::thread_rng();
75+
let random_pos = rand::distributions::Uniform::new::<f64, f64>(0., sequence_length.into());
76+
let mut tables = tskit::TableCollection::new(sequence_length).unwrap();
77+
let child = tables.add_node(0, 0.0, -1, -1).unwrap();
78+
let parent = tables.add_node(0, 1.0, -1, -1).unwrap();
79+
let mut left = tskit::Position::from(random_pos.sample(&mut rng));
80+
let mut right = tskit::Position::from(random_pos.sample(&mut rng));
81+
if left > right {
82+
std::mem::swap(&mut left, &mut right);
83+
}
84+
85+
// ANCHOR: get_edge_table_columns
86+
if let Ok(edge_id) = tables.add_edge(left, right, parent, child) {
87+
// Take a reference to an edge table (& tskit::EdgeTable)
88+
let edges = tables.edges();
89+
if let Some(p) = edges.parent(edge_id) {
90+
assert_eq!(p, parent);
91+
}
92+
if let Some(c) = edges.child(edge_id) {
93+
assert_eq!(c, child);
94+
}
95+
if let Some(l) = edges.left(edge_id) {
96+
assert_eq!(l, left);
97+
}
98+
if let Some(r) = edges.right(edge_id) {
99+
assert_eq!(r, right);
100+
}
101+
} else {
102+
panic!("that should have worked...");
103+
}
104+
// ANCHOR_END: get_edge_table_columns
105+
106+
// ANCHOR: get_edge_table_columns_out_of_range
107+
assert!(tables.edges().parent(tskit::EdgeId::NULL).is_none());
108+
// ANCHOR_END: get_edge_table_columns_out_of_range
109+
110+
let edge_id = tskit::EdgeId::from(0);
111+
// ANCHOR: get_edge_table_row_by_id
112+
if let Some(row) = tables.edges().row(edge_id) {
113+
assert_eq!(row.id, 0);
114+
assert_eq!(row.left, left);
115+
assert_eq!(row.right, right);
116+
assert_eq!(row.parent, parent);
117+
assert_eq!(row.child, child);
118+
} else {
119+
panic!("that should have worked...");
120+
}
121+
// ANCHOR_END: get_edge_table_row_by_id
122+
123+
// ANCHOR: get_edge_table_rows_by_iterator
124+
for row in tables.edges_iter() {
125+
// there is only one row!
126+
assert_eq!(row.id, 0);
127+
assert_eq!(row.left, left);
128+
assert_eq!(row.right, right);
129+
assert_eq!(row.parent, parent);
130+
assert_eq!(row.child, child);
131+
}
132+
// ANCHOR_END: get_edge_table_rows_by_iterator
133+
134+
assert!(tables
135+
.check_integrity(tskit::TableIntegrityCheckFlags::default())
136+
.is_ok());
137+
}

0 commit comments

Comments
 (0)