// Bioconductor SpatialDecon-inspired background-aware spatial deconvolution.
///|
fn main {
let (data, profile, nuclei_counts) = @src.spatial_decon_example_data() catch {
SpatialDeconError(message) => abort("example data failed: " + message)
}
let config = @src.SpatialDeconConfig::create(
rescale_profile=false,
tolerance=1.0e-9,
) catch {
SpatialDeconError(message) => abort("invalid configuration: " + message)
}
let result = @src.spatial_decon(data, profile, nuclei_counts~, config~) catch {
SpatialDeconError(message) => abort("deconvolution failed: " + message)
}
println("=== Background-aware spatial deconvolution ===")
println(result.summary())
println("spot\tcell type\tabundance\tproportion\tcells")
for spot in 0.. abort("ranking failed: " + message)
}
for entry in ranked {
let cell_type = entry.cell_type
let mut cell_index = 0
while result.cell_types[cell_index] != cell_type {
cell_index = cell_index + 1
}
println(
entry.spot_id +
"\t" +
cell_type +
"\t" +
entry.abundance.to_string() +
"\t" +
entry.proportion.to_string() +
"\t" +
result.cell_counts[cell_index][spot].to_string(),
)
}
}
println("fit diagnostics:")
for spot in 0.. abort("invalid cell merge: " + message)
}
let myeloid = @src.SpatialDeconCellMerge::create("Myeloid", ["Myeloid"]) catch {
SpatialDeconError(message) => abort("invalid cell merge: " + message)
}
let collapsed = @src.collapse_spatial_decon(result, [lymphoid, myeloid]) catch {
SpatialDeconError(message) => abort("cell-type collapse failed: " + message)
}
println("\n=== Collapsed cell types ===")
for group in 0..
abort("reverse deconvolution failed: " + message)
}
println("\n=== Reverse deconvolution ===")
println("first-gene intercept=" + reverse.coefficients[0][0].to_string())
for cell_type in 0..
abort("background estimation failed: " + message)
}
println("\n=== Probe-pool background ===")
for row in background {
println(row[0].to_string() + "\t" + row[1].to_string())
}
let learned_profile = @src.create_spatial_decon_profile(
["g1", "g2", "g3"],
["a1", "a2", "b1", "b2"],
["A", "A", "B", "B"],
[[10.0, 8.0, 1.0, 2.0], [1.0, 2.0, 9.0, 11.0], [2.0, 2.0, 2.0, 2.0]],
normalize=true,
scaling_factor=5.0,
min_cells=1,
min_genes=0,
) catch {
SpatialDeconError(message) =>
abort("profile construction failed: " + message)
}
println("\n=== Single-cell-derived profile ===")
println(
"genes=" +
learned_profile.n_genes().to_string() +
", cell types=" +
learned_profile.n_cell_types().to_string(),
)
for cell_type in learned_profile.cell_types {
println("profile cell type: " + cell_type)
}
let experiment = @src.SpatialExperiment::new()
ignore(@src.se_add_assay(experiment, "counts", data.values))
ignore(@src.se_add_assay(experiment, "background", data.background))
for gene in data.gene_names {
ignore(@src.se_add_row(experiment, Map([("gene_id", gene)])))
}
for spot in 0..
abort("SpatialExperiment integration failed: " + message)
}
println("\n=== SpatialExperiment integration ===")
println(
"genes=" +
integrated.experiment.metadata["spatialdecon_genes"] +
", spots=" +
integrated.experiment.metadata["spatialdecon_spots"] +
", original unchanged=" +
(!experiment.col_data[0].contains("SpatialDecon:T_cell")).to_string(),
)
}