///|
/// clusterExperiment RSEC workflow demo.
///
/// Demonstrates consensus and sequential clustering on synthetic
/// high-dimensional biological data using the RSEC pipeline.
fn main {
println("=== clusterExperiment RSEC Demo ===\n")
// Create synthetic data: 3 well-separated clusters in 5D space
let data : Array[Array[Double]] = Array(capacity=0)
// Cluster 0: 10 samples centered at (1, 1, 1, 1, 1)
for i in 0..<10 {
let pt = Array(capacity=0)
for _j in 0..<5 {
pt.push(1.0 + (i.to_double() - 5.0) * 0.05)
}
data.push(pt)
}
// Cluster 1: 10 samples centered at (5, 5, 5, 5, 5)
for i in 0..<10 {
let pt = Array(capacity=0)
for _j in 0..<5 {
pt.push(5.0 + (i.to_double() - 5.0) * 0.05)
}
data.push(pt)
}
// Cluster 2: 8 samples centered at (9, 1, 9, 1, 9)
for i in 0..<8 {
let pt = Array(capacity=0)
pt.push(9.0 + (i.to_double() - 4.0) * 0.05)
pt.push(1.0 + (i.to_double() - 4.0) * 0.05)
pt.push(9.0 + (i.to_double() - 4.0) * 0.05)
pt.push(1.0 + (i.to_double() - 4.0) * 0.05)
pt.push(9.0 + (i.to_double() - 4.0) * 0.05)
data.push(pt)
}
println("Input: " + data.length().to_string() + " samples, 5 features")
println("Expected: 3 clusters (10 + 10 + 8 samples)\n")
// Get default RSEC parameters
let params = @bio.ce_default_params()
println("RSEC Parameters:")
println(" k values: [2, 3, 4]")
println(" reduced dims: [0, 5]")
println(" subsamples: [1.0, 0.8]")
println(" merge cutoff: " + params.merge_cutoff.to_string())
println(" sequential alpha: " + params.sequential_alpha.to_string())
println("")
// Step 1: clusterMany - ensemble of clusterings
let ensemble = @bio.ce_cluster_many(data, params)
println(
"clusterMany: generated " + ensemble.length().to_string() + " clusterings",
)
// Step 2: Co-clustering matrix
let cocluster = @bio.ce_cocluster_matrix(ensemble, data.length())
println(
"Co-clustering matrix: " +
cocluster.length().to_string() +
"x" +
cocluster.length().to_string(),
)
// Print a small sample of the co-clustering matrix
println("\nCo-clustering matrix (first 5x5 block):")
for i in 0..<5 {
let mut row = ""
for j in 0..<5 {
row = row + cocluster[i][j].to_string() + " "
}
println(" " + row)
}
// Step 3: Consensus clustering
let consensus_labels = @bio.ce_make_consensus(cocluster, 3)
println("\nConsensus clustering (k=3):")
let consensus_sizes = @bio.ce_cluster_sizes(consensus_labels)
let mut ci = 0
while ci < consensus_sizes.length() {
let (id, size) = consensus_sizes[ci]
println(
" cluster " + id.to_string() + ": " + size.to_string() + " samples",
)
ci = ci + 1
}
// Step 4: Dendrogram
let dendro = @bio.ce_make_dendrogram(data, consensus_labels)
println(
"\nDendrogram built: " + (if dendro is Some(_) { "yes" } else { "no" }),
)
// Step 5: Merge clusters by significance
let (merged_labels, merge_info) = @bio.ce_merge_clusters(
data,
consensus_labels,
dendro,
params.merge_cutoff,
)
println(
"Merge clusters: " +
merge_info.length().to_string() +
" merge steps evaluated",
)
let mut merged_count = 0
for info in merge_info {
if info.merged {
merged_count = merged_count + 1
}
}
println(" " + merged_count.to_string() + " merges applied")
// Step 6: Sequential clustering
let seq_labels = @bio.ce_sequential_cluster(
data,
merged_labels,
params.sequential_alpha,
params.sequential_beta,
)
let n_seq = @bio.ce_count_clusters(seq_labels)
println("\nSequential clustering: " + n_seq.to_string() + " final clusters")
// Full RSEC pipeline
println("\n--- Full RSEC Pipeline ---")
let result = @bio.ce_rsec(data, params)
println(@bio.ce_summary(result))
// Show per-sample assignments
println("Per-sample cluster assignments:")
let mut i = 0
while i < result.labels.length() {
let label_str = result.labels[i].to_string()
let mut line = " sample " + i.to_string() + " -> cluster " + label_str
if i < 10 {
line = line + " (cluster 0 group)"
} else if i < 20 {
line = line + " (cluster 1 group)"
} else {
line = line + " (cluster 2 group)"
}
println(line)
i = i + 1
}
println("\n=== Demo Complete ===")
}