///|
/// Primer3 module demo - PCR primer design and analysis.
///
/// Run: moon run examples/primer3_demo
fn main {
println("=== Primer3 Module Demo ===")
println(
"PCR primer design with Tm calculation, GC content, and complementarity scoring",
)
println("Reference: Rozen S, Skaletsky H (2000) Methods Mol Biol 132:365-86")
println("")
// ------------------------------------------------------------------
// 1. GC content calculation
// ------------------------------------------------------------------
println("=== 1. GC Content Calculation ===")
let seq1 = "ATGCGTACGTAGATGCGTAC"
let gc1 = @bio.primer3_gc_content(seq1)
println("Sequence: \{seq1}")
println("GC content: \{gc1 * 100.0}%")
println("")
let seq2 = "GGCCGGCCGGCCGGCCGGCC"
let gc2 = @bio.primer3_gc_content(seq2)
println("Sequence: \{seq2}")
println("GC content: \{gc2 * 100.0}%")
println("")
// ------------------------------------------------------------------
// 2. Melting temperature (Tm) calculation
// ------------------------------------------------------------------
println("=== 2. Melting Temperature (Tm) ===")
let short_seq = "AATTGC"
let tm_wallace = @bio.primer3_tm_wallace(short_seq)
println("Short oligo (\{short_seq}):")
println(" Wallace rule Tm: \{tm_wallace} C")
println("")
let long_seq = "ATGCGTACGTAGATGCGTAC"
let tm_salt = @bio.primer3_tm_salt(long_seq, 0.05)
let tm_auto = @bio.primer3_tm(long_seq, 0.05)
println("Longer primer (\{long_seq}):")
println(" Salt-adjusted Tm (50mM Na+): \{tm_salt} C")
println(" Auto-selected Tm: \{tm_auto} C")
println("")
// ------------------------------------------------------------------
// 3. Self-complementarity and cross-dimer scoring
// ------------------------------------------------------------------
println("=== 3. Complementarity Scoring ===")
let primer1 = "GAATTC"
let sc = @bio.primer3_self_complement(primer1)
println("Primer: \{primer1}")
println(" Self-complementarity score: \{sc} (lower is better)")
let hp = @bio.primer3_hairpin_3prime(primer1, 4)
println(" 3' hairpin potential (last 4 nt): \{hp}")
println("")
let primer2 = "ATGCATGC"
let cd = @bio.primer3_cross_dimer(primer1, primer2)
println("Cross-dimer between \{primer1} and \{primer2}: \{cd}")
println("")
// ------------------------------------------------------------------
// 4. Primer design pipeline
// ------------------------------------------------------------------
println("=== 4. Primer Design Pipeline ===")
let cfg = @bio.Primer3Config::new(
18, 22, 40.0, 75.0, 0.3, 0.8, 8, 8, 0.05, 50,
)
let template = @bio.primer3_sample_template()
println("Template length: \{template.length()} bp")
println(
"Config: len=\{cfg.primer_length_min()}-\{cfg.primer_length_max()}, Tm=\{cfg.tm_min()}-\{cfg.tm_max()}, GC=\{cfg.gc_min() * 100.0}-\{cfg.gc_max() * 100.0}%",
)
println("")
let design = @bio.primer3_design_primers(template, cfg)
println("Forward candidates: \{design.n_forward()}")
println("Reverse candidates: \{design.n_reverse()}")
println("Has pair: \{design.has_pair()}")
println("")
// ------------------------------------------------------------------
// 5. Display best primers
// ------------------------------------------------------------------
println("=== 5. Best Primer Candidates ===")
match design.best_forward() {
Some(f) => println("Best forward: \{f.to_string()}")
None => println("Best forward: (none)")
}
match design.best_reverse() {
Some(r) => println("Best reverse: \{r.to_string()}")
None => println("Best reverse: (none)")
}
println("")
// ------------------------------------------------------------------
// 6. Amplicon length
// ------------------------------------------------------------------
println("=== 6. Amplicon Information ===")
match design.best_pair() {
Some((f, r)) => {
let amp_len = @bio.primer3_pair_amplicon_length(f, r)
println("Best pair amplicon length: \{amp_len} bp")
}
None => println("No primer pair available")
}
println("")
// ------------------------------------------------------------------
// 7. Display top 5 forward and reverse candidates
// ------------------------------------------------------------------
println("=== 7. Top Primer Candidates ===")
let fwds = design.forward()
let n_fwd_show = if fwds.length() < 5 { fwds.length() } else { 5 }
println("Top \{n_fwd_show} forward primers:")
for i in 0..