Skip to content

Commit 9d0dd5c

Browse files
committed
Add TableCollection::topological_sort_individuals.
Closes #195
1 parent 4c17ca6 commit 9d0dd5c

File tree

4 files changed

+80
-2
lines changed

4 files changed

+80
-2
lines changed

examples/forward_simulation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* and numbers of crossovers, etc.., from being entered
1919
* on the command line.
2020
*/
21-
use clap::{Command, Arg};
21+
use clap::{Arg, Command};
2222
use rand::rngs::StdRng;
2323
use rand::Rng;
2424
use rand::SeedableRng;

examples/tree_traversals.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clap::{Command, Arg};
1+
use clap::{Arg, Command};
22
use tskit::prelude::*;
33

44
// "Manual" traversal from samples to root

src/flags.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ bitflags! {
103103
}
104104
}
105105

106+
bitflags! {
107+
/// Modify behavior of [`crate::TableCollection::sort_individuals`].
108+
#[derive(Default)]
109+
pub struct IndividualTableSortOptions : tsk_flags_t {
110+
/// Default behavior.
111+
const NONE = 0;
112+
}
113+
}
114+
106115
bitflags! {
107116
/// Specify the behavior of iterating over [`Tree`] objects.
108117
/// See [`TreeSequence::tree_iterator`].

src/table_collection.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::metadata::*;
55
use crate::types::Bookmark;
66
use crate::EdgeTable;
77
use crate::IndividualTable;
8+
use crate::IndividualTableSortOptions;
89
use crate::Location;
910
use crate::MigrationTable;
1011
use crate::MutationTable;
@@ -597,6 +598,12 @@ impl TableCollection {
597598
/// Sort the tables.
598599
/// The [``bookmark``](crate::types::Bookmark) can
599600
/// be used to affect where sorting starts from for each table.
601+
///
602+
/// # Warning
603+
///
604+
/// As of `0.7.0`, this function does not sort the individual table!
605+
/// See
606+
/// [``topological_sort_individuals``](crate::TableCollection::topological_sort_individuals).
600607
pub fn sort(&mut self, start: &Bookmark, options: TableSortOptions) -> TskReturnValue {
601608
let rv = unsafe {
602609
ll_bindings::tsk_table_collection_sort(
@@ -611,11 +618,73 @@ impl TableCollection {
611618

612619
/// Fully sort all functions.
613620
/// Implemented via a call to [``sort``](crate::TableCollection::sort).
621+
///
622+
/// # Warning
623+
///
624+
/// As of `0.7.0`, this function does not sort the individual table!
625+
/// See
626+
/// [``topological_sort_individuals``](crate::TableCollection::topological_sort_individuals).
614627
pub fn full_sort(&mut self, options: TableSortOptions) -> TskReturnValue {
615628
let b = Bookmark::new();
616629
self.sort(&b, options)
617630
}
618631

632+
/// Sorts the individual table in place, so that parents come before children,
633+
/// and the parent column is remapped as required. Node references to individuals
634+
/// are also updated.
635+
///
636+
/// This function is needed because neither [``sort``](crate::TableCollection::sort) nor
637+
/// [``full_sort``](crate::TableCollection::full_sort) sorts
638+
/// the individual table!
639+
///
640+
/// # Examples
641+
///
642+
/// ```
643+
/// // Parent comes AFTER the child
644+
/// let mut tables = tskit::TableCollection::new(1.0).unwrap();
645+
/// let i0 = tables.add_individual::<i32, f64>(0,&[],&[1]).unwrap();
646+
/// assert_eq!(i0, 0);
647+
/// let i1 = tables.add_individual::<i32, f64>(0,&[],&[]).unwrap();
648+
/// assert_eq!(i1, 1);
649+
/// let n0 = tables.add_node(0, 0.0, -1, i1).unwrap();
650+
/// assert_eq!(n0, 0);
651+
/// let n1 = tables.add_node(0, 1.0, -1, i0).unwrap();
652+
/// assert_eq!(n1, 1);
653+
///
654+
/// // Testing for valid individual order will Err:
655+
/// match tables.check_integrity(tskit::TableIntegrityCheckFlags::CHECK_INDIVIDUAL_ORDERING) {
656+
/// Ok(_) => panic!("expected Err"),
657+
/// Err(_) => (),
658+
/// };
659+
///
660+
/// // The standard sort doesn't fix the Err...:
661+
/// tables.full_sort(tskit::TableSortOptions::default()).unwrap();
662+
/// match tables.check_integrity(tskit::TableIntegrityCheckFlags::CHECK_INDIVIDUAL_ORDERING) {
663+
/// Ok(_) => panic!("expected Err"),
664+
/// Err(_) => (),
665+
/// };
666+
///
667+
/// // ... so we need to intentionally sort the individuals.
668+
/// let _ = tables.topological_sort_individuals(tskit::IndividualTableSortOptions::default()).unwrap();
669+
/// tables.check_integrity(tskit::TableIntegrityCheckFlags::CHECK_INDIVIDUAL_ORDERING).unwrap();
670+
/// ```
671+
///
672+
/// # Errors
673+
///
674+
/// Will return an error code if the underlying `C` function returns an error.
675+
pub fn topological_sort_individuals(
676+
&mut self,
677+
options: IndividualTableSortOptions,
678+
) -> TskReturnValue {
679+
let rv = unsafe {
680+
ll_bindings::tsk_table_collection_individual_topological_sort(
681+
self.as_mut_ptr(),
682+
options.bits(),
683+
)
684+
};
685+
handle_tsk_return_value!(rv)
686+
}
687+
619688
/// Dump the table collection to file.
620689
///
621690
pub fn dump(&self, filename: &str, options: TableOutputOptions) -> TskReturnValue {

0 commit comments

Comments
 (0)