///|
/// UMI 分子标签演示: header 提取 -> 5' 剪除 -> 去重 -> 纠错 -> 共识.
fn main raise {
println(
"=== UMI 提取 / 去重 / 纠错 (umi_tools 风格, 本地完成) ===",
)
// 模拟测序 read: UMI 通过下划线后缀携带, 5' 端含 UMI 碱基.
let headers = ["@read1_ACGTACGT", "@read2_ACGTACGT", "@read3_ACGAACGT"]
let raw_seqs = ["ACGTACGTAAAA", "ACGTACGTAATA", "ACGAACGTAAAT"]
let raw_quals = ["IIIIIIIIIIII", "IIIIIIIIIIII", "IIIIIIIIIIII"]
println("\n1. header 解析 + UMI 剪除")
let reads : Array[@src.UmiRead] = Array(capacity=0)
for i = 0; i < headers.length(); i = i + 1 {
let parsed = @src.umi_parse_header(headers[i], @src.Underscore)
let q = @src.umi_qualities_from_ascii(raw_quals[i])
let (seq, qual) = @src.umi_clip_read(raw_seqs[i], q, parsed.umi.length())
println(" \{parsed.name}: UMI=\{parsed.umi}, 剪除后=\{seq}")
reads.push(@src.UmiRead::{
id: parsed.name,
sequence: seq,
qualities: qual,
umi: parsed.umi,
chrom: "chr1",
pos: 100,
strand: 1,
})
}
println("\n2. 按 (UMI, locus) 去重并生成共识")
let families = @src.umi_dedup(reads)
for f in families {
println(
" UMI=\{f.umi} pos=\{f.pos} family_size=\{f.size} consensus=\{f.consensus}",
)
}
println("\n3. directional UMI 纠错 (编辑距离 <= 1)")
let corrected = @src.umi_directional_correct(families)
for f in corrected {
println(" 代表 UMI=\{f.umi} 合并后 size=\{f.size}")
}
println("\n4. 汇总统计")
let stats = @src.umi_stats(corrected)
println(
" families=\{stats.n_families}, reads=\{stats.n_reads}, singletons=\{stats.singleton_families}, mean_quality=\{stats.mean_quality}",
)
println("\n5. JSON 输出")
println(@src.umi_families_to_json(corrected))
println("完成: UMI 链路全程本地处理, 数据不出本机.")
}