///|
/// Biostrings PDict dictionary matching demo.
///
/// Demonstrates creating a pattern dictionary (PDict) with restriction enzyme
/// recognition patterns, matching patterns against DNA sequences, vectorized
/// counting across multiple subjects, and using which/which_index functions.
///
/// Run: moon run examples/biostrings_matchdict_demo/main.mbt
fn main {
println("=== PDict Dictionary Matching Demo ===")
println("")
println("1. Creating a PDict with restriction enzyme patterns")
// Restriction enzymes recognize specific short DNA sequences
let patterns = ["GAATTC", "AAGCTT", "GGATCC", "GTCGAC"]
let enzyme_names = ["EcoRI", "HindIII", "BamHI", "SalI"]
let pdict = @bio.bmd_create_pdict(patterns~)
println(" Patterns loaded: \{pdict.patterns.length()}")
let mut p = 0
while p < patterns.length() {
println(" \{enzyme_names[p]}: \{patterns[p]}")
p = p + 1
}
println("")
println("2. Matching patterns against a DNA sequence")
let subject = "ATGCGAATTCTTAAGCTTGGATCCGTCGACATGC"
println(" Subject: \{subject}")
let match_result = @bio.bmd_match_pdict(pdict~, subject~)
println(" Total hits found: \{match_result.hits.length()}")
let mut h = 0
while h < match_result.hits.length() {
let hit = match_result.hits[h]
println(
" Hit \{h}: pattern=\"\{hit.pattern}\" (\{enzyme_names[hit.pattern_idx]}), start=\{hit.start}, end=\{hit.end}, mismatches=\{hit.mismatches}",
)
h = h + 1
}
println("")
println("3. Matching with allowed mismatches")
// Create a PDict allowing 1 mismatch
let pdict_mm = @bio.bmd_create_pdict(patterns~, max_mismatches=1)
let mm_result = @bio.bmd_match_pdict(
pdict=pdict_mm,
subject="ATGCGAATTXCTTAAGCTTGGATCC",
)
println(" With max_mismatches=1, hits found: \{mm_result.hits.length()}")
h = 0
while h < mm_result.hits.length() {
let hit = mm_result.hits[h]
println(
" Hit \{h}: pattern=\"\{hit.pattern}\", start=\{hit.start}, mismatches=\{hit.mismatches}",
)
h = h + 1
}
println("")
println("4. Vectorized countPattern across multiple sequences")
let subjects = [
"GAATTCGAATTCGAATTC", "AAGCTTGCATGCAAGCTT", "TTTTTTTTTTTTTTTTTT", "GAATTCAAGCTTGGATCC",
]
println(" Subjects (\{subjects.length()} sequences):")
let mut s = 0
while s < subjects.length() {
println(" \{s}: \{subjects[s]}")
s = s + 1
}
let vcount_result = @bio.bmd_vcount_pattern(pattern="GAATTC", subjects~)
println("")
println(" vcountPattern for \"GAATTC\":")
println(" Total occurrences: \{vcount_result.total}")
s = 0
while s < vcount_result.counts.length() {
println(" Subject \{s}: \{vcount_result.counts[s]} occurrences")
s = s + 1
}
println("")
println("5. Vectorized matching of multiple patterns")
let multi_patterns = ["GAATTC", "AAGCTT"]
let multi_results = @bio.bmd_vmatch_pattern(
patterns=multi_patterns,
subjects~,
)
let mut mp = 0
while mp < multi_results.length() {
let r = multi_results[mp]
println(
" Pattern \"\{r.pattern}\": total=\{r.total}, counts=\{Repr(r.counts)}",
)
mp = mp + 1
}
println("")
println("6. which/which_index: finding subjects with matches")
// Create a PDict with a single pattern for which/which_index
let pdict_single = @bio.bmd_create_pdict(patterns=["GAATTC"])
let which_result = @bio.bmd_which(pdict=pdict_single, subjects~)
println(" which() results (GAATTC in each subject):")
s = 0
while s < which_result.length() {
println(" Subject \{s}: \{which_result[s]}")
s = s + 1
}
let which_indices = @bio.bmd_which_index(pdict=pdict_single, subjects~)
println(" which_index() returns matching indices: \{Repr(which_indices)}")
println("")
println("7. Counting total pattern occurrences")
let total = @bio.bmd_count_occurrences(pdict~, subject~)
println(" Total pattern occurrences in subject: \{total}")
println("")
println("8. Finding best match (fewest mismatches)")
let best = @bio.bmd_find_best_match(
pdict=pdict_mm,
subject="ATGCGAATTXCTTAAGCTTGGATCC",
)
match best {
Some(hit) =>
println(
" Best match: pattern=\"\{hit.pattern}\", mismatches=\{hit.mismatches}, start=\{hit.start}",
)
None => println(" No matches found")
}
println("")
println("=== Demo Complete ===")
}