lineage/chromosome
Represents the chromosomal structure of an individual’s genome.
A Chromosome holds the alleles for all genes located on a single
physical chromosome. A ChromosomeSet groups chromosomes by their
identity (autosome number, X, Y, or other), with one list of chromosomes
per identity to support any ploidity.
This module also provides the core operations needed for the reproductive cycle: creating new chromosomes from a gene map, forming gametes via random halving, merging two gametes into an offspring genome, and extracting the alleles carried at each gene position.
Types
A single chromosome: a mapping from gene index (position on the chromosome) to the allele carried at that position
pub type Chromosome =
dict.Dict(Int, String)
Identifies which chromosome within the genome a set of genes belongs to.
Mirrors gene.GenePosition but strips the per-gene index, so that all
genes on the same physical chromosome share the same ChromosomeIndex.
Autosome(no)— autosome identified by its chromosome numberX— X gonosomeY— Y gonosomeOther(name)— any non-standard chromosome type, identified by name
pub type ChromosomeIndex {
Autosome(no: Int)
X
Y
Other(name: String)
}
Constructors
-
Autosome(no: Int) -
X -
Y -
Other(name: String)
The full chromosomal genome of an individual.
Maps each ChromosomeIndex to a list of chromosomes of that type.
The length of each list reflects the ploidity of the individual:
a diploid individual will have two chromosomes per index.
pub type ChromosomeSet =
dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String)))
An ordered list of genes that defines the genome of a species
pub type GeneMap =
List(gene.Gene)
pub type TypedChromosomeSet =
dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, #(gene.Gene, String))),
)
Values
pub fn annotate_set(
chromosomes: dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, String)),
),
definitions: List(gene.Gene),
) -> dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, #(gene.Gene, String))),
)
Annotates a ChromosomeSet with gene metadata, producing a TypedChromosomeSet.
For each chromosome index in the set, the genes from definitions that
belong to that index are looked up by their offset. Each allele in the raw
chromosome is then paired with its Gene, producing a TypedChromosome.
Offsets with no matching gene in definitions are silently dropped.
Examples
let typed = annotate_set(individual.genome, pea.genome())
pub fn create_gamete(
chromosomes: dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, String)),
),
) -> dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String)))
Creates a gamete from a chromosome set by randomly selecting half of the chromosomes at each index.
For a diploid individual this yields one chromosome per index, as expected for a haploid gamete. The halving is random, so each call may produce a different result.
Examples
let gamete = create_gamete(diploid_genome)
// each chromosome list in gamete has length 1 (half of 2)
pub fn drain(
chromosomes: dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, String)),
),
index: ChromosomeIndex,
) -> dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String)))
Reduces the chromosomes at a given index to a random half, removing the entry entirely if it was already empty.
Unlike create_gamete, which acts on the whole set, drain targets a
single chromosome index. Returns the chromosome set unchanged if the index
is not present.
pub fn encode_chromosome(
chromosome: dict.Dict(Int, String),
) -> json.Json
Encodes a single chromosome as a JSON object.
Keys are the gene indices (as strings) and values are the allele strings.
Examples
encode_chromosome(chromosome) |> json.to_string
// -> "{\"50\":\"R\",\"35\":\"G\"}"
pub fn encode_set(
chromosomes: dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, String)),
),
) -> json.Json
Encodes a full chromosome set as a JSON object.
Keys are chromosome identifiers produced by index_to_string. Each value
is a JSON array of encoded chromosomes, one per copy at that index.
Examples
encode_set(genome) |> json.to_string
// -> "{\"1\":[{...},{...}],\"X\":[{...}]}"
pub fn extract_genes(
chromosome: dict.Dict(Int, String),
index: ChromosomeIndex,
genes: List(gene.Gene),
) -> dict.Dict(gene.Gene, String)
Extracts the allele carried at each gene position from a single chromosome.
The chromosome’s offset-keyed entries are matched against the full
GenePosition of each gene in the gene map using reverse_index.
Only genes whose position falls on the given index chromosome will
produce results.
Examples
let alleles = extract_genes(chromosome, Autosome(3), pea.genome())
// -> dict mapping each gene on chromosome 3 to its allele
pub fn extract_genes_from_set(
chromosomes: List(dict.Dict(Int, String)),
index: ChromosomeIndex,
genes: List(gene.Gene),
) -> dict.Dict(gene.Gene, List(String))
Extracts alleles across a list of chromosomes at the same index, grouping them into a list per gene.
Calls extract_genes on each chromosome and collects the results so that
each gene maps to all the alleles it carries across the set — one per
chromosome copy.
Examples
let alleles = extract_genes_from_set(diploid_chr3, Autosome(3), pea.genome())
// -> each gene on chromosome 3 maps to a list of 2 alleles
pub fn index(position: gene.GenePosition) -> ChromosomeIndex
Converts a gene.GenePosition to the ChromosomeIndex of the chromosome
it belongs to, discarding the per-gene offset.
Examples
index(gene.Autosome(3, 70))
// -> Autosome(3)
index(gene.X(12))
// -> X
pub fn index_to_string(index: ChromosomeIndex) -> String
Converts a ChromosomeIndex to a human-readable string.
Autosomes are represented by their number, gonosomes by "X" or "Y",
and other chromosomes by "Other " followed by the name.
Examples
index_to_string(Autosome(3))
// -> "3"
index_to_string(X)
// -> "X"
index_to_string(Other("plastid"))
// -> "Other plastid"
pub fn indices(
definitions: List(gene.Gene),
) -> set.Set(ChromosomeIndex)
Returns the set of distinct chromosome indices present in a gene map.
Examples
indices(pea.genome())
// -> set containing Autosome(1), Autosome(2), Autosome(3), Autosome(4), Autosome(5)
pub fn map_to_genes(
chromosomes: dict.Dict(
ChromosomeIndex,
List(dict.Dict(Int, String)),
),
genes: List(gene.Gene),
) -> dict.Dict(gene.Gene, List(String))
Maps an entire chromosome set to a dict of genes and their allele lists.
Iterates over every chromosome index in the set, calls
extract_genes_from_set for each, and merges the results. The final dict
maps each Gene to all alleles it carries across all chromosomes and all
copies — the full genotype ready for expression.
Examples
let genotype = map_to_genes(individual.genome, pea.genome())
// -> dict mapping each gene to a list of alleles (length = ploidity)
pub fn merge(
left: dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String))),
right: dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String))),
) -> dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String)))
Merges two chromosome sets into one by concatenating the chromosome lists at each index.
Keys present in only one of the two sets are included as-is. This is the operation used to combine the two gametes produced during mating.
Examples
let offspring_genome = merge(father_gamete, mother_gamete)
pub fn new(
definitions: List(gene.Gene),
) -> dict.Dict(Int, String)
Creates a single chromosome from a gene map by sampling one allele per gene.
Each gene contributes one entry to the chromosome, keyed by its index on
the chromosome. Genes from different chromosome types may be mixed in
definitions; all will be included regardless.
Examples
let chr = new(pea.genome())
dict.size(chr)
// -> 7
pub fn new_set(
definitions: List(gene.Gene),
amount: Int,
) -> dict.Dict(ChromosomeIndex, List(dict.Dict(Int, String)))
Creates a new full chromosome set from a gene map at a given ploidity.
For each distinct chromosome index in the gene map, amount chromosomes
are created by randomly sampling alleles for the genes on that chromosome.
Examples
let genome = new_set(pea.genome(), 2)
dict.size(genome)
// -> 5 (one entry per autosome: 1, 2, 3, 4, 5)
pub fn reverse_index(
index: ChromosomeIndex,
offset: Int,
) -> gene.GenePosition
Reconstructs a gene.GenePosition from a ChromosomeIndex and an offset.
This is the inverse of index: given the chromosome identity and the
position of a gene on that chromosome, it returns the full GenePosition.
Examples
reverse_index(Autosome(3), 70)
// -> gene.Autosome(3, 70)
reverse_index(X, 12)
// -> gene.X(12)