Skip to content

Commit

Permalink
doc: add mdbook
Browse files Browse the repository at this point in the history
* add gh-pages.yml
* Make sure book examples work for MSRV
* default to light theme
  • Loading branch information
molpopgen committed Nov 4, 2022
1 parent f6d3a94 commit 272f365
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: github pages

on:
push:
branches:
- main
release:
types: [created]
pull_request:

jobs:
deploy:
runs-on: ubuntu-20.04
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- uses: actions/checkout@v3

- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: 'latest'

- run: mdbook build book

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
if: github.event_name == 'release'
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book
9 changes: 9 additions & 0 deletions book/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[book]
authors = ["Kevin R. Thornton"]
language = "en"
multilingual = false
src = "src"
title = "The tskit (rust) book"

[output.html]
preferred-dark-theme = "light"
7 changes: 7 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Summary

- [Introduction](./introduction.md)
- [Working with table collections](./working_with_table_collections.md)
- [Creation](./table_collection_creation.md)
- [Adding rows](./table_collection_adding_rows.md)
- [Validating table collection contents](./table_collection_validation.md)
42 changes: 42 additions & 0 deletions book/src/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Introduction <img align="right" width="73" height="45" src="https://raw.githubusercontent.com/tskit-dev/administrative/main/logos/svg/tskit-rust/Tskit_rust_logo.eps.svg">

## Do you need `tskit-rust`?

The use-cases for `tskit-rust` are the same as for `tskit-c`:

1. Developing a new performance-oriented application.
2. The input/output of this application will be a `.trees` file.

## What does `tskit-rust` add?

Briefly, you get the performance of `C` and the strong safety guarantees of `rust`.

## What is `tskit-rust` missing?

The crate does not cover the entire `C` API.
However, client code can make direct calls to that API via the module `tskit::bindings`.

## Adding `tskit` as a dependency to a rust project

In your `Cargo.toml`:

```{toml}
[dependencies]
tskit = "~X.Y.Z"
```

The latest version to fill in `X.Y.Z` can be found [here](https://crates.io/crates/tskit).
See [here](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html) for how to specify version numbers.

### Feature flags.

`tskit` defines several [cargo features](https://doc.rust-lang.org/cargo/reference/features.html).
These are defined in the [API docs](https://docs.rs/tskit/latest/tskit/#optional-features).

## Conventions used in this document

We assume a working knowledge of rust.
Thus, we skip over the details of things like matching idioms, etc.,
and just `.unwrap()`.

We also assume familiarity with the `tskit` [data model](https://tskit.dev/tskit/docs/stable/data-model.html).
26 changes: 26 additions & 0 deletions book/src/table_collection_adding_rows.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
## Adding rows to tables

* For each table type (node, edge., etc.), we have a function to add a row.
* We can only add rows to tables in mutable `TableCollection` instances.

For example, to add a node:


```rust, noplaygound, ignore
{{#include ../../tests/book_table_collection.rs:add_node_without_metadata}}
```

We see from the `if let` pattern that functions adding rows return
[`Result`](https://doc.rust-lang.org/std/result/enum.Result.html).
In general, errors only occur when the C back-end fails to allocate memory
to expand the table columns.
If we add a row with invalid data, no error is returned!
To catch such errors, we must explicitly check table integrity (see [below](table_collection_validation.md#checking-table-integrity)).

Again, we can take advantage of being able to pass in any type that is `Into<_>` the required newtype:

```rust, noplaygound, ignore
{{#include ../../tests/book_table_collection.rs:add_node_without_metadata_using_into}}
```

See the [API docs](https://docs.rs/tskit) for more details and examples.
18 changes: 18 additions & 0 deletions book/src/table_collection_creation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
## Creation

We initialize a `TableCollection` with a sequence length.
In `tskit-c`, the genome length is a C `double`.
Here it is a [newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html) called `tskit::Position`:

```rust, noplaygound, ignore
{{#include ../../tests/book_table_collection.rs:create_table_collection_with_newtype}}
```

The newtype pattern gives type safety by disallowing you to send a position to a function where a time is required, etc..
However, it can be inconvenient to type out the full type names every time.
Thus, the API defines most functions taking arguments `Into<T>` where `T` is one of our newtypes.
This design means that the following is equivalent to what we wrote above:

```rust, noplaygound, ignore
{{#include ../../tests/book_table_collection.rs:create_table_collection}}
```
11 changes: 11 additions & 0 deletions book/src/table_collection_validation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Checking table integrity

The data model involves lazy checking of inputs.
In other words, we can add invalid row data that is not caught by the "add row" functions.
We inherit this behavior from the C API.

We can check that the tables contain valid data by:

```rust, noplaygound, ignore
{{#include ../../tests/book_table_collection.rs:integrity_check}}
```
3 changes: 3 additions & 0 deletions book/src/working_with_table_collections.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Working with table collections <img align="right" width="73" height="45" src="https://raw.githubusercontent.com/tskit-dev/administrative/main/logos/svg/tskit-rust/Tskit_rust_logo.eps.svg">

The next sections cover how to work with the `TableCollection`, which is one of `tskit`'s fundamental types.
68 changes: 68 additions & 0 deletions tests/book_table_collection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#[test]
fn simple_table_collection_creation_with_newtype() {
// ANCHOR: create_table_collection_with_newtype
let sequence_length = tskit::Position::from(100.0);
if let Ok(tables) = tskit::TableCollection::new(sequence_length) {
assert_eq!(tables.sequence_length(), sequence_length);
// In tskit, the various newtypes can be compared to
// the low-level types they wrap.
assert_eq!(tables.sequence_length(), 100.0);
} else {
panic!(
"TableCollection creation sequence length = {} failed",
sequence_length
);
}
// ANCHOR_END: create_table_collection_with_newtype
}

#[test]
fn simple_table_collection_creation() {
// ANCHOR: create_table_collection
let tables = tskit::TableCollection::new(100.0).unwrap();
// ANCHOR_END: create_table_collection
assert_eq!(tables.sequence_length(), 100.0);
}

#[test]
fn add_node_without_metadata() {
{
// ANCHOR: add_node_without_metadata
let mut tables = tskit::TableCollection::new(100.0).unwrap();
if let Ok(node_id) = tables.add_node(
0, // Node flags
tskit::Time::from(0.0), // Birth time
tskit::PopulationId::NULL, // Population id
tskit::IndividualId::NULL, // Individual id
) {
assert_eq!(node_id, 0);
}
// ANCHOR_END: add_node_without_metadata
}
{
let mut tables = tskit::TableCollection::new(100.0).unwrap();
// ANCHOR: add_node_without_metadata_using_into
let node_id = tables.add_node(0, 0.0, -1, -1).unwrap();
// ANCHOR_END: add_node_without_metadata_using_into
assert_eq!(node_id, 0);
}
}

#[test]
fn add_node_handle_error() {
// ANCHOR: integrity_check
let mut tables = tskit::TableCollection::new(100.0).unwrap();
// Everything about this edge is wrong...
tables.add_edge(-1.0, 110.0, 0, 1).unwrap();
// ...and we can catch that here
match tables.check_integrity(tskit::TableIntegrityCheckFlags::default()) {
Ok(code) => panic!("expected Err(e) but got code: {}", code),
// tskit::TskitError can be formatted into the same
// error messages that tskit-c/tskit-python give.
Err(e) => println!("{}", e),
}
// ANCHOR_END: integrity_check
assert!(tables
.check_integrity(tskit::TableIntegrityCheckFlags::default())
.is_err());
}

0 comments on commit 272f365

Please sign in to comment.