///|
/// gene_pop module demo - GenePop file format parsing and analysis.
///
/// Demonstrates parsing of GenePop population genetics files, including
/// genotype extraction, allele frequency calculation, and heterozygosity
/// statistics.
///
/// Reference: Biopython Bio.PopGen.GenePop
/// Run: moon run examples/gene_pop_demo
fn main {
println("=== gene_pop Module Demo ===")
println("GenePop file format parsing and analysis")
println("Reference: Biopython Bio.PopGen.GenePop")
println("")
// ------------------------------------------------------------------
// 1. Parse sample GenePop file
// ------------------------------------------------------------------
println("=== 1. Parse Sample GenePop File ===")
let sample = @bio.genepop_sample()
let record = @bio.parse_genepop(sample)
println("Title: " + record.title)
println("Loci digit size: " + record.locus_digit_size.to_string())
println("Loci names: " + record.loci_names.length().to_string())
let mut li = 0
while li < record.loci_names.length() {
println(" Locus " + (li + 1).to_string() + ": " + record.loci_names[li])
li = li + 1
}
println("Populations: " + @bio.genepop_num_populations(record).to_string())
println(
"Total individuals: " + @bio.genepop_total_individuals(record).to_string(),
)
println("")
// ------------------------------------------------------------------
// 2. Population and individual details
// ------------------------------------------------------------------
println("=== 2. Population and Individual Details ===")
let mut pi = 0
while pi < record.populations.length() {
let pop = record.populations[pi]
println(
"Population: " +
pop.name +
" individuals: " +
pop.individuals.length().to_string(),
)
let mut ii = 0
while ii < pop.individuals.length() {
let ind = pop.individuals[ii]
let mut geno_str = ""
let mut gi = 0
while gi < ind.genotypes.length() {
let g = ind.genotypes[gi]
if gi > 0 {
geno_str = geno_str + " "
}
match g.allele2 {
Some(a2) =>
geno_str = geno_str + g.allele1.to_string() + "/" + a2.to_string()
None => geno_str = geno_str + g.allele1.to_string()
}
gi = gi + 1
}
println(" " + ind.name + ": " + geno_str)
ii = ii + 1
}
pi = pi + 1
}
println("")
// ------------------------------------------------------------------
// 3. Allele frequencies
// ------------------------------------------------------------------
println("=== 3. Allele Frequencies (Locus 1) ===")
let mut ppi = 0
while ppi < record.populations.length() {
let pop = record.populations[ppi]
let freqs = @bio.genepop_allele_frequencies(pop, 0)
println("Population " + pop.name + ":")
let keys = freqs.keys()
let key_arr : Array[Int32] = []
let mut ki = 0
for k in keys {
key_arr.push(k)
ki = ki + 1
}
// Simple bubble sort for deterministic ordering.
let mut a = 0
while a < key_arr.length() {
let mut b = a + 1
while b < key_arr.length() {
if key_arr[b] < key_arr[a] {
let tmp = key_arr[a]
key_arr[a] = key_arr[b]
key_arr[b] = tmp
}
b = b + 1
}
a = a + 1
}
let mut si = 0
while si < key_arr.length() {
let allele = key_arr[si]
let freq = freqs.get_or_default(allele, 0.0)
println(" Allele " + allele.to_string() + ": " + freq.to_string())
si = si + 1
}
ppi = ppi + 1
}
println("")
// ------------------------------------------------------------------
// 4. Heterozygosity statistics
// ------------------------------------------------------------------
println("=== 4. Heterozygosity Statistics (Locus 1) ===")
let mut hi = 0
while hi < record.populations.length() {
let pop = record.populations[hi]
let obs = @bio.genepop_observed_heterozygosity(pop, 0)
let exp = @bio.genepop_expected_heterozygosity(pop, 0)
println(
"Population " +
pop.name +
": observed=" +
obs.to_string() +
" expected=" +
exp.to_string(),
)
hi = hi + 1
}
println("")
// ------------------------------------------------------------------
// 5. Round-trip serialization
// ------------------------------------------------------------------
println("=== 5. Round-trip Serialization ===")
let serialized = @bio.genepop_to_string(record)
let reparsed = @bio.parse_genepop(serialized)
println(
"Re-parsed populations: " +
@bio.genepop_num_populations(reparsed).to_string(),
)
println(
"Re-parsed individuals: " +
@bio.genepop_total_individuals(reparsed).to_string(),
)
println("Digit size preserved: " + reparsed.locus_digit_size.to_string())
println("")
// ------------------------------------------------------------------
// 6. Summary report
// ------------------------------------------------------------------
println("=== 6. Summary Report ===")
println(@bio.genepop_summary(record))
println("")
println("=== Demo Complete ===")
}