diff --git a/CHANGELOG.md b/CHANGELOG.md index b50eabbf..85b6b00e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # task_spatial_simulators dev Bug fixes: + - `downstream`: normalise the simulated dataset the same way as the real one, + through a new `compute_logcounts()` helper. The simulated side used + `log1p(counts)` while the real side used the stored, size-factor normalised + `logcounts`. On the positive control, `crosscor_cosine` and + `crosscor_mantel` now come out at exactly 1. - `scdesign2`: order the input by `spatial_cluster` before simulating. `simulate_count_scDesign2()` returns cells grouped per cell type, so the coordinates taken from the unsorted input belonged to different spots than diff --git a/src/helpers/utils.R b/src/helpers/utils.R index 28e58c96..1063f51a 100644 --- a/src/helpers/utils.R +++ b/src/helpers/utils.R @@ -1,3 +1,28 @@ +# log-normalisation +# +# Both the real and the simulated dataset must be normalised the exact same way +# before they are compared, otherwise the metric picks up the difference in +# normalisation rather than the difference in the data. Do not read the +# `logcounts` layer directly: on the real dataset it was produced by the dataset +# loader, on a simulated dataset it may not exist at all. +compute_logcounts <- function(adata) { + requireNamespace("scater", quietly = TRUE) + requireNamespace("SingleCellExperiment", quietly = TRUE) + requireNamespace("SummarizedExperiment", quietly = TRUE) + + # genes x spots, as expected by SingleCellExperiment + counts <- Matrix::t(adata$layers[["counts"]]) + + sce <- SingleCellExperiment::SingleCellExperiment(list(counts = counts)) + sce <- scater::logNormCounts(sce) + + logcounts <- SummarizedExperiment::assay(sce, "logcounts") + dimnames(logcounts) <- dimnames(counts) + + # back to spots x genes, matching the anndata layout + Matrix::t(logcounts) +} + # spatial autocorrelation generate_moransI <- function(adata) { requireNamespace("spots", quietly = TRUE) diff --git a/src/metrics/downstream/script.R b/src/metrics/downstream/script.R index 6aa44784..f03009c8 100644 --- a/src/metrics/downstream/script.R +++ b/src/metrics/downstream/script.R @@ -33,9 +33,9 @@ ctdeconvolute_rmse <- generate_rmse(real_ct_prop, sim_ct_prop) ctdeconvolute_jsd <- generate_jds(real_ct_prop, sim_ct_prop) cat("spatial autocorrelation evaluation\n") -counts <- input_simulated_sp$layers[["counts"]] -logcounts <- log1p(counts) -input_simulated_sp$layers[["logcounts"]] <- logcounts +# normalise both datasets the same way, so that Moran's I is comparable +input_real_sp$layers[["logcounts"]] <- compute_logcounts(input_real_sp) +input_simulated_sp$layers[["logcounts"]] <- compute_logcounts(input_simulated_sp) real_moransI <- generate_moransI(input_real_sp) # real_moransI <- input_real_sp$varm$spatial_autocorrelation sim_moransI <- generate_moransI(input_simulated_sp)