@@ -5,6 +5,7 @@ use crate::metadata::*;
55use crate :: types:: Bookmark ;
66use crate :: EdgeTable ;
77use crate :: IndividualTable ;
8+ use crate :: IndividualTableSortOptions ;
89use crate :: Location ;
910use crate :: MigrationTable ;
1011use 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+ /// # Note
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+ /// # Note
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