Contributing¶
Bug reports, especially ones with a reproducer, are the most useful thing you can send.
Reporting a bug¶
Open an issue with:
- the exact command
fstic --version- the stderr output, which carries the filter echo, the warning counts and the summary
- a minimal input that shows the problem, ideally a couple of small VCFs
A wrong number is worth reporting even without a reproducer. Say what you expected and why, since the estimators have variants that differ in ways that are easy to mistake for a bug and vice versa.
Building and testing¶
git clone https://github.com/PathoGenOmics-Lab/fstic.git
cd fstic
cargo build
cargo test
cargo clippy --all-targets
Please keep cargo test green and add no new clippy warnings.
Adding an estimator¶
Each lives in its own file under src/calculation/ and exposes one function
taking the two samples' PositionalData, the sorted locus list, and whatever
flags it honours.
Use the shared helpers rather than rolling your own loop:
get_all_freqs_at_posbuilds both frequency vectors at a locus, with the reference allele imputed. It is where the "absent means reference" rule lives, so calling it is what keeps a new estimator consistent with the rest.sum_per_locusandsum_per_locus_naccumulate per-locus terms in a thread-count-independent order. A plainpar_iter().sum()will make the output depend on--workers.heterozygosityandpooled_heterozygosityfor the GST family.
Then register it in the Formula enum in src/cli.rs and the match in
src/main.rs.
Tests a new estimator needs¶
Look at src/calculation/tests.rs for the shape. At minimum:
- identical samples give exactly 0
- symmetry:
d(a, b) == d(b, a) - a hand-computed value at intermediate frequencies, which is the one that catches a wrong formula. Identity and fixed-difference cases often agree between two different estimators, so they cannot tell them apart on their own.
- the theoretical bound
- if the estimator is cumulative, that a locus absent from both samples
contributes nothing (see
absent_site_is_neutral_for_cumulative_metrics)
Assert on parsed numbers, not on substrings of the output file. The diagonal is
hard-coded to zero, so content.contains("0.000000") passes on any matrix at
all; the off_diagonal helper in tests/integration.rs exists for this.
Documentation¶
The site is MkDocs Material.
CI builds with --strict, so a broken internal link or a page missing from the
nav fails the build rather than shipping. If you change behaviour, the page
describing it and CHANGELOG.md should move with the code.
Licence¶
GPL-3.0. Contributions are accepted under the same terms.