///|
/// 组装图简化与共识抛光演示:
/// GFA 图 -> tip 裁剪 / containment 坍缩 / bubble 解析 -> 统计,
/// 参考序列 + 模拟读段 -> racon-lite 抛光 -> 修正报告.
fn demo_repeat(base : Char, len : Int32) -> String {
let sb = StringBuilder()
for _i in 0.. String {
let bases = "ACGT"
let sb = StringBuilder()
let rng = @src.Rng::new(20261030UL)
for _i in 0.. Int32 {
let n = if a.length() < b.length() { a.length() } else { b.length() }
let mut diff = 0
let mut i = 0
while i < n {
if a.unsafe_get(i) != b.unsafe_get(i) {
diff = diff + 1
}
i = i + 1
}
diff +
(if a.length() > b.length() {
a.length() - b.length()
} else {
b.length() - a.length()
})
}
///|
fn demo_has_segment(graph : @src.GfaGraph, name : String) -> Bool {
match @src.gfa_get_segment(graph, name) {
Some(_) => true
None => false
}
}
///|
fn main {
println("=== 组装图简化与共识抛光 (racon-lite) ===")
// ---- 1. 构造含短死端与 bubble 的 GFA 图 ----
let unit = demo_repeat('A', 120)
let gfa_text = "H\tVN:Z:1.0\n" +
"S\tentry\t" +
unit +
"\n" +
"S\ta1\t" +
unit +
"\tDP:i:10\n" +
"S\ta2\t" +
unit +
"\tDP:i:10\n" +
"S\tb1\t" +
unit +
"\tDP:i:2\n" +
"S\texit\t" +
unit +
"\n" +
"S\ttip\t" +
demo_repeat('T', 20) +
"\n" +
"L\tentry\t+\ta1\t+\t0M\n" +
"L\ta1\t+\ta2\t+\t0M\n" +
"L\ta2\t+\texit\t+\t0M\n" +
"L\tentry\t+\tb1\t+\t0M\n" +
"L\tb1\t+\texit\t+\t0M\n" +
"L\tentry\t+\ttip\t+\t0M\n" +
"P\tp_tip\tentry+,a1+,a2+,exit+,tip+\t0M,0M,0M,0M\n" +
"P\tp_main\tentry+,a1+,a2+,exit+\t0M,0M,0M\n"
let graph = @src.gfa_parse(gfa_text)
println("\n原始图: \{@src.gfa_graph_summary(graph)}")
let bubbles = @src.assembly_detect_bubbles(graph)
println(
"原始图直接检测 bubble: \{bubbles.length()} (tip 使 entry 出度为 3, 需先裁剪 tip)",
)
// ---- 2. 简化 ----
let simplified = @src.assembly_simplify(graph)
let stats = simplified.stats()
println("\n简化统计 JSON: \{@src.assembly_simplify_stats_to_json(stats)}")
println("简化后图: \{@src.gfa_graph_summary(simplified.graph())}")
let keep_a1 = demo_has_segment(simplified.graph(), "a1")
let keep_b1 = demo_has_segment(simplified.graph(), "b1")
let keep_tip = demo_has_segment(simplified.graph(), "tip")
println("保留 a1: \{keep_a1}")
println("保留 b1: \{keep_b1}")
println("保留 tip: \{keep_tip}")
println("保留 path 数: \{@src.gfa_graph_n_paths(simplified.graph())}")
// ---- 3. 模拟读段并抛光 ----
let reference = demo_reference(400)
println("\n参考序列长度: \{reference.length()}")
let mut sim_fastq = ""
let mut n_reads = 0
try {
let sim_config = @src.read_simulator_config(
read_length=100,
coverage=30.0,
paired_end=false,
error_rate=0.02,
snp_rate=0.01,
indel_rate=0.003,
seed=7UL,
)
let sim = @src.simulate_reads(reference, config=sim_config)
sim_fastq = sim.fastq
n_reads = sim.n_reads
println(
"模拟读段: \{sim.n_reads} 条, 实际覆盖度=\{sim.achieved_coverage}, 错误碱基数=\{sim.n_errors}",
)
} catch {
@src.ReadSimulatorError(message) =>
println("读段模拟失败: \{message}")
}
if sim_fastq == "" {
return
}
let reads : Array[String] = Array(capacity=n_reads)
try {
let records = @src.parse_fastq(sim_fastq)
for record in records {
reads.push(record.seq.to_string())
}
} catch {
_ => println("FASTQ 解析失败")
}
let mut polished_done = false
try {
let config = @src.polish_config(k=15, min_coverage=3, min_fraction=0.6)
let result = @src.racon_polish(reference, reads, config~)
println(
"\n抛光结果: reads_used=\{result.reads_used()}/\{result.reads_total()}",
)
println("平均覆盖度: \{result.mean_coverage()}")
println("采纳修正数: \{result.edits().length()}")
let edits = result.edits()
let shown = if edits.length() < 8 { edits.length() } else { 8 }
for i in 0.. \{edit.new_base()} (support=\{edit.support()}/\{edit.coverage()})",
)
}
let mut n_sub = 0
let mut n_del = 0
let mut n_ins = 0
for edit in result.edits() {
if edit.kind() == "substitution" {
n_sub = n_sub + 1
} else if edit.kind() == "deletion" {
n_del = n_del + 1
} else {
n_ins = n_ins + 1
}
}
println(
"修正分类: 替换=\{n_sub} 删除=\{n_del} 插入=\{n_ins}; consensus 长度=\{result.consensus().length()} (参考 \{reference.length()})",
)
ignore(demo_diff_count(result.consensus(), reference))
println("JSON: \{@src.polish_result_to_json(result)}")
polished_done = true
} catch {
@src.AssemblyGraphError(message) => println("抛光失败: \{message}")
}
if polished_done {
println("\n演示完成: 图简化与读段共识抛光闭环")
}
}