///|
/// SeqCode demo: Biopython Bio.SeqUtils helpers for amino-acid code
/// conversion, GC fraction / codon-position GC, IUPAC-aware nucleotide
/// search and six-frame translation.
///
/// Run: moon run examples/seqcode_demo
fn main {
println("=== SeqCode Demo (Bio.SeqUtils advanced) ===\n")
// 1. One-letter -> three-letter amino-acid codes (seq3)
println("1. seq3: one-letter to three-letter codes")
let protein = "MAIVMGRWKGAR*"
println(" seq3(MAIVMGRWKGAR*) = \{@bio.seq3(protein)}")
let star3 = @bio.seq3(protein, custom_map=Map([("*", "***")]))
println(" seq3 with custom_map star->*** = \{star3}")
let extended3 = @bio.seq3("BXZJUO*")
println(" seq3(BXZJUO*) (IUPAC extended) = \{extended3}")
// 2. Three-letter -> one-letter codes (seq1), case insensitive
println("\n2. seq1: three-letter to one-letter codes")
let three = "MetAlaIleValMetGlyArgTrpLysGlyAlaArgTer"
println(" seq1(MetAla..ArgTer) = \{@bio.seq1(three)}")
let mixed_case = @bio.seq1("METalaIlEValMetGLYArgTer")
println(" seq1 is case insensitive: \{mixed_case}")
let extended1 = @bio.seq1("AsxGlxXleSecPylTer")
println(" seq1(AsxGlxXleSecPylTer) = \{extended1}")
// 3. GC fraction with ambiguous base handling (gc_fraction)
println("\n3. gc_fraction: GC content between 0 and 1")
let plain = @bio.gc_fraction("ACTG") catch { _ => 0.0 }
println(" gc_fraction(ACTG) = \{plain}")
let ign = @bio.gc_fraction("ACTGN", ambiguous="ignore") catch { _ => 0.0 }
println(" gc_fraction(ACTGN, ignore) = \{ign}")
let wgt = @bio.gc_fraction("ACTGN", ambiguous="weighted") catch { _ => 0.0 }
println(" gc_fraction(ACTGN, weighted) = \{wgt}")
let rem = @bio.gc_fraction("GDVV", ambiguous="remove") catch { _ => 0.0 }
println(" gc_fraction(GDVV, remove) = \{rem}")
// 4. GC content per codon position (GC123)
println("\n4. gc123: total and per-codon-position GC percentages")
let coding = "ATGGCCATTGTAATGGGCCGCTGAAAGGGTGCCCGATAG"
let r = @bio.gc123(coding)
println(" sequence (39 nt), GC total = \{r.gc_all}%")
println(" GC pos1 = \{r.gc1}% GC pos2 = \{r.gc2}% GC pos3 = \{r.gc3}%")
// 5. IUPAC ambiguous nucleotide search (nt_search)
println("\n5. nt_search: IUPAC-aware forward-strand search")
let hits = @bio.nt_search("GATCGATCGA", "NGA") catch {
_ => abort("valid IUPAC query should never fail")
}
println(" pattern for NGA = \{hits.pattern}")
println(" positions in GATCGATCGA = \{join_positions(hits.positions)}")
// 6. Six-frame translation with GC content
println("\n6. six_frame_translations")
let sft = @bio.six_frame_translations("AUGGCCAUUGUAAUGGGCCGCUGA") catch {
_ => abort("standard genetic code should never fail")
}
println(sft)
println("=== Demo Complete ===")
}
///|
/// Render a list of integers as "1, 2, 3" for display.
fn join_positions(positions : Array[Int32]) -> String {
let buf = StringBuilder()
for i = 0; i < positions.length(); i = i + 1 {
if i > 0 {
buf.write_string(", ")
}
buf.write_string(positions[i].to_string())
}
buf.to_string()
}