|
| 1 | +cat("Loading dependencies\n") |
| 2 | +requireNamespace("anndata", quietly = TRUE) |
| 3 | +library(Matrix, warn.conflicts = FALSE) |
| 4 | +requireNamespace("scMerge", quietly = TRUE) |
| 5 | +requireNamespace("BiocParallel", quietly = TRUE) |
| 6 | +requireNamespace("BiocSingular", quietly = TRUE) |
| 7 | +requireNamespace("methods", quietly = TRUE) |
| 8 | + |
| 9 | +## VIASH START |
| 10 | +par <- list( |
| 11 | + input = "resources_test/task_batch_integration/cxg_immune_cell_atlas/dataset.h5ad", |
| 12 | + output = "output.h5ad", |
| 13 | + cell_type_aware = FALSE, |
| 14 | + n_control_genes = 1000L, |
| 15 | + n_dim = 50L |
| 16 | +) |
| 17 | +meta <- list( |
| 18 | + name = "scmerge2", |
| 19 | + cpus = 1L |
| 20 | +) |
| 21 | +## VIASH END |
| 22 | + |
| 23 | +n_cpus <- if (is.null(meta$cpus)) 1L else meta$cpus |
| 24 | +bpparam <- BiocParallel::MulticoreParam(workers = n_cpus) |
| 25 | + |
| 26 | +cat("Read input\n") |
| 27 | +adata <- anndata::read_h5ad(par$input) |
| 28 | + |
| 29 | +# both scSEGIndex and scMerge2 want genes in the rows. scMerge2 only coerces a *dense* matrix to |
| 30 | +# CsparseMatrix, so a row-compressed one would slip past that check and break later on |
| 31 | +exprs_mat <- methods::as(Matrix::t(adata$layers[["normalized"]]), "CsparseMatrix") |
| 32 | +rownames(exprs_mat) <- as.character(adata$var_names) |
| 33 | +colnames(exprs_mat) <- as.character(adata$obs_names) |
| 34 | + |
| 35 | +cat("Select stably expressed genes\n") |
| 36 | +seg_df <- scMerge::scSEGIndex(exprs_mat = exprs_mat, BPPARAM = bpparam) |
| 37 | +seg_df <- seg_df[order(seg_df$segIdx, decreasing = TRUE), , drop = FALSE] |
| 38 | +ctl <- rownames(seg_df)[seq_len(min(par$n_control_genes, nrow(seg_df)))] |
| 39 | + |
| 40 | +cat("Run scMerge2\n") |
| 41 | +out <- scMerge::scMerge2( |
| 42 | + exprsMat = exprs_mat, |
| 43 | + batch = as.character(adata$obs$batch), |
| 44 | + cellTypes = if (par$cell_type_aware) as.character(adata$obs$cell_type) else NULL, |
| 45 | + ctl = ctl, |
| 46 | + use_bpparam = bpparam, |
| 47 | + use_bsparam = BiocSingular::RandomParam(), |
| 48 | + verbose = TRUE |
| 49 | +) |
| 50 | + |
| 51 | +cat("Compute embedding\n") |
| 52 | +newY <- out$newY |
| 53 | +stopifnot(ncol(newY) == adata$n_obs) |
| 54 | +if (!is.null(colnames(newY))) { |
| 55 | + newY <- newY[, adata$obs_names, drop = FALSE] |
| 56 | +} |
| 57 | +# subtracting the estimated unwanted variation makes the corrected matrix dense, so let |
| 58 | +# BiocSingular stream it rather than materialising it in one go |
| 59 | +corrected <- t(newY) |
| 60 | +n_dim <- min(par$n_dim, min(dim(corrected)) - 1L) |
| 61 | +embedding <- BiocSingular::runPCA( |
| 62 | + corrected, |
| 63 | + rank = n_dim, |
| 64 | + center = TRUE, |
| 65 | + scale = FALSE, |
| 66 | + BSPARAM = BiocSingular::RandomParam(), |
| 67 | + BPPARAM = bpparam |
| 68 | +)$x |
| 69 | +rownames(embedding) <- adata$obs_names |
| 70 | + |
| 71 | +cat("Store output\n") |
| 72 | +output <- anndata::AnnData( |
| 73 | + obs = adata$obs[, c()], |
| 74 | + var = adata$var[, c()], |
| 75 | + obsm = list( |
| 76 | + X_emb = embedding |
| 77 | + ), |
| 78 | + uns = list( |
| 79 | + dataset_id = adata$uns[["dataset_id"]], |
| 80 | + normalization_id = adata$uns[["normalization_id"]], |
| 81 | + method_id = meta$name |
| 82 | + ) |
| 83 | +) |
| 84 | + |
| 85 | +cat("Write output to file\n") |
| 86 | +zzz <- output$write_h5ad(par$output, compression = "gzip") |
0 commit comments