///|
/// TwoBitIO demo - UCSC .2bit binary genome format reader/writer.
///
/// Run: moon run examples/twobit_demo
fn main {
println("=== TwoBitIO Demo ===")
println("UCSC 2bit binary sequence format")
println("Reference: UCSC Genome Browser 2bit format specification")
println("")
// ------------------------------------------------------------------
// 1. Load sample 2bit file
// ------------------------------------------------------------------
println("=== 1. Load sample 2bit file ===")
let tbf = @bio.twobit_sample_file()
println("Loaded sample 2bit file")
println("")
// ------------------------------------------------------------------
// 2. Print file info (n_sequences, sequence names, dna sizes)
// ------------------------------------------------------------------
println("=== 2. File info ===")
println("n_sequences: \{tbf.n_sequences()}")
let names = tbf.sequence_names()
println("sequence names count: \{names.length()}")
for n in names {
match tbf.get_sequence(n) {
Some(s) => println(" \{n}: dna_size=\{s.dna_size()}")
None => println(" \{n}: not found")
}
}
println("")
// ------------------------------------------------------------------
// 3. Extract sequences as strings and print
// ------------------------------------------------------------------
println("=== 3. Extract sequences as strings ===")
for n in names {
match @bio.twobit_get_sequence_string(tbf, n) {
Some(s) => println(" \{n}: \{s}")
None => println(" \{n}: not found")
}
}
println("")
// ------------------------------------------------------------------
// 4. Show N blocks for seq2
// ------------------------------------------------------------------
println("=== 4. N blocks for seq2 ===")
match tbf.get_sequence("seq2") {
Some(seq2) => {
let n_blocks = seq2.n_blocks()
println("seq2 has \{n_blocks.length()} N-block(s)")
for b in n_blocks {
println(" start=\{b.start()}, size=\{b.size()}, end=\{b.end()}")
}
}
None => println("seq2 not found")
}
println("")
// ------------------------------------------------------------------
// 5. Demonstrate pack/unpack round-trip
// ------------------------------------------------------------------
println("=== 5. Pack/unpack round-trip ===")
let dna = "ATGCNNNNATGC"
let (packed, n_blocks, mask_blocks) = @bio.twobit_pack_sequence(dna)
let unpacked = @bio.twobit_unpack_sequence(
packed,
dna.length(),
n_blocks,
mask_blocks,
)
println("Original: \{dna}")
println("Unpacked: \{unpacked}")
println("Match: \{dna == unpacked}")
println("")
// ------------------------------------------------------------------
// 6. Serialize to bytes and back, verify
// ------------------------------------------------------------------
println("=== 6. Serialize to bytes and back ===")
let bytes = @bio.twobit_to_bytes(tbf)
println("Serialized to \{bytes.length()} bytes")
let restored = @bio.twobit_from_bytes(bytes)
println("Restored n_sequences: \{restored.n_sequences()}")
for n in restored.sequence_names() {
match @bio.twobit_get_sequence_string(restored, n) {
Some(s) => println(" \{n}: \{s}")
None => println(" \{n}: not found")
}
}
println("")
// ------------------------------------------------------------------
// 7. Serialize to hex string and back, verify
// ------------------------------------------------------------------
println("=== 7. Serialize to hex string and back ===")
let hex = @bio.twobit_write(tbf)
println("Hex string length: \{hex.length()}")
let hex_restored = @bio.twobit_read(hex)
println("Restored n_sequences: \{hex_restored.n_sequences()}")
for n in hex_restored.sequence_names() {
match @bio.twobit_get_sequence_string(hex_restored, n) {
Some(s) => println(" \{n}: \{s}")
None => println(" \{n}: not found")
}
}
println("")
// ------------------------------------------------------------------
// 8. Convert to SeqRecord array and show
// ------------------------------------------------------------------
println("=== 8. Convert to SeqRecord array ===")
let recs = @bio.twobit_to_seq_records(tbf)
println("Converted to \{recs.length()} SeqRecord(s)")
for rec in recs {
println(" \{rec.repr()}")
}
println("")
// ------------------------------------------------------------------
// 9. Create from a DNA string and verify
// ------------------------------------------------------------------
println("=== 9. Create from a DNA string ===")
let new_dna = "GGGATCCCATGC"
let new_rec = @bio.SeqRecord::new(
@bio.Seq::new(new_dna),
id="custom",
name="custom",
description="Created from a DNA string",
)
let new_file = @bio.twobit_from_seq_records([new_rec])
match @bio.twobit_get_sequence_string(new_file, "custom") {
Some(s) => {
println("Original: \{new_dna}")
println("Extracted: \{s}")
println("Match: \{new_dna == s}")
}
None => println("custom sequence not found")
}
println("")
println("=== Demo complete ===")
}