# lineage

[![Package Version](https://img.shields.io/hexpm/v/lineage)](https://hex.pm/packages/lineage)
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/lineage/)
[![License](https://img.shields.io/badge/license-BSD--3--Clause-blue)](./LICENSE)


A Mendelian genetics simulation library and CLI for educational use.

`lineage` models genes, chromosomes, individuals, and populations at the level
of classical genetics. It is designed to be used either as an Erlang/OTP
application that emits JSON, or as a Gleam library compiled to JavaScript for
use in interactive web-based teaching tools.

## Running the CLI

The default target (`lineage.gleam`, compiled for Erlang/OTP) simulates a
population of garden peas (*Pisum sativum*) over a number of generations and
writes the result to disk.

```sh
gleam run                  # 10 individuals, 10 generations (defaults)
gleam run -- 100 20        # 100 individuals, 20 generations
```

A random individual from the final population is chosen as the center of a
family tree. Three files are written to the current directory, all sharing
one freshly generated UUID as their basename:

- `<uuid>.json` - the full population keyed by generation number, with each
  individual's name (UUID), sex, fertility, parentage, phenotype, and raw
  genome
- `<uuid>-phenotype.svg` - the chosen individual's family tree, rendered with
  each member's expressed phenotype icons
- `<uuid>-genes.svg` - the same family tree, rendered with each member's raw
  genotype badges instead

The UUID and the three file paths are printed to stdout once the files have
been written.

## Running the UI

`lineage/ui.gleam` is a browser-based [Lustre](https://hexdocs.pm/lustre/) app for
interactively exploring a simulated population — browsing individuals by
generation, filtering by phenotype, and inspecting a family tree — compiled
to JavaScript instead of Erlang/OTP.

```sh
gleam build --target=javascript
```

Then serve the project root with any static file server (opening
`index.html` directly via `file://` won't work, since it loads the compiled
app as an ES module) and open it in a browser, e.g.:

```sh
python3 -m http.server
```

`index.html` loads `build/dev/javascript/lineage/lineage/ui.mjs` and calls its
`main` function, along with `crypto-shim.mjs`, which polyfills the Node
`node:crypto` import that `gleam_crypto`/`youid` pull in on the JavaScript
target.

## Core concepts

### Gene and alleles

A `Gene` has a name, a fixed position on a chromosome, a set of valid alleles,
and an optional expression rule that maps a list of alleles to a phenotype.

### Expression rules

The `gene/dominance` module provides ready-made expression rules. `simple`
covers classical dominant-recessive inheritance:

```gleam
import lineage/gene
import lineage/gene/dominance
import gleam/set
import gleam/option

let seed_shape = gene.Gene(
  "Seed shape",
  gene.Autosome(5, 50),
  set.from_list(["R", "w"]),
  option.Some(dominance.simple(#("R", "round"), #("w", "wrinkled"))),
)
```

### Species rules

A `SpeciesRules` value bundles a genome (list of genes), ploidity, a sex
predicate, and a fertility predicate into a single configuration that is passed
to individual and population functions.

```gleam
import lineage/individual

let rules = individual.SpeciesRules(
  individual.no_sex,
  2,
  individual.always_fertile,
  genome,
)
```

### Population simulation

```gleam
import lineage/population
import lineage/species/pea

let rules = population.PopulationRules(
  population.select_all,
  function.identity,
  fn(_) { 20 },
)

pea.create_multiple(20)
|> population.from_list
|> population.simulate(5, rules)
```

### Garden pea reference species

The `lineage/species/pea` module provides a ready-to-use definition of Mendel's seven
traits from his original pea experiments: seed shape, stem length, cotyledon
colour, flower colour, pod colour, pod form, and flower position.

## Project structure

```
src/
  lineage.gleam                  # CLI entry point
  lineage/
    gene.gleam                   # Gene, Allele, GenePosition types; JSON encode/decode
    gene/dominance.gleam         # Expression rules (simple dominance)
    chromosome.gleam             # Chromosome, ChromosomeSet, gamete formation
    individual.gleam             # Individual, mating, phenotype resolution
    population.gleam             # Population, generational simulation
    heritage.gleam                # Ancestry/family-tree graph
    algorithms.gleam             # Shared collection utilities
    species/pea.gleam            # Pisum sativum species definition
    export/svg.gleam             # Family-tree SVG export
    ui.gleam                     # Browser UI (Lustre, JavaScript target)
```

## Development

```sh
gleam run          # Run the CLI with default arguments
gleam test         # Run the test suite
gleam docs build   # Build HTML documentation
```
