OSCR

SpNeigh: spatial neighborhood and differential expression analysis for high-resolution spatial transcriptomics.

Code ↔ Paper

40 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 40 matches · 13 of them tie a paragraph to a whole file, not to given lines: weak matches, whose lines are not tinted
  1. [1] § Materials and methods › Data preparation for SpNeigh ↔ inst/script/generate_vignette_data.R, the whole file · a weak match · score 0.93 · FindClusters, FindNeighbors, RunPCA, ScaleData, RunUMAP, NormalizeData
  2. [2] § Materials and methods › Data preparation for SpNeigh ↔ source_code/00_Prepare.Rmd, lines 161–195 · score 0.88 · FindClusters, FindNeighbors, RunPCA, ScaleData, RunUMAP, NormalizeData
  3. [3] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Gradient-based spatial differential expression ↔ R/RunDE.R, lines 268–328 · score 0.88 · QR decomposition, augmented matrix, positively correlated, spline basis, design matrix, orthonormalize
  4. [4] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Gradient-based spatial differential expression ↔ R/RunDE.R, lines 268–328 · score 0.88 · QR decomposition, augmented matrix, positively correlated, spline basis, design matrix, orthonormalize
  5. [5] § Materials and methods › Analysis of human healthy liver MERFISH dataset using SpNeigh ↔ R/RunDE.R, lines 147–265 · score 0.88 · natural splines, computeBoundaryWeights, models gene expression, smooth function, runSpatialDE, getBoundary
  6. [6] § Materials and methods › Analysis of human healthy liver MERFISH dataset using SpNeigh ↔ R/RunDE.R, lines 147–265 · score 0.88 · natural splines, ComputeBoundaryWeights, models gene expression, smooth function, RunSpatialDE, GetBoundary
  7. [7] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Gradient-based spatial differential expression ↔ R/RunDE.R, lines 268–328 · score 0.82 · natural cubic spline, spline basis, design matrix, spatial distance, freedom, ns
  8. [8] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Gradient-based spatial differential expression ↔ R/RunDE.R, lines 268–328 · score 0.82 · natural cubic spline, spline basis, design matrix, spatial distance, freedom, ns
  9. [9] § Materials and methods › Analysis of mouse brain Xenium dataset using SpNeigh ↔ R/GetBoundary.R, lines 684–756 · score 0.81 · getOuterBoundary, buildBoundaryPoly, getRingRegion, Boundary polygons, getBoundary, ring regions
  10. [10] § Materials and methods › Analysis of mouse brain Xenium dataset using SpNeigh ↔ R/GetBoundary.R, lines 560–632 · score 0.81 · GetOuterBoundary, BuildBoundaryPoly, GetRingRegion, Boundary polygons, GetBoundary, ring regions
  11. [11] § Materials and methods › Benchmarking differential expression and spatial modeling in SpNeigh ↔ R/RunDE.R, lines 1–143 · score 0.80 · log fold changes, min.pct, log FC, runLimmaDE, mouse brain, Seurat
  12. [12] § Materials and methods › Benchmarking differential expression and spatial modeling in SpNeigh ↔ R/RunDE.R, lines 1–143 · score 0.80 · log fold changes, min.pct, log FC, RunLimmaDE, mouse brain, Seurat
  13. [13] § Materials and methods › Analysis of human breast cancer Xenium dataset using SpNeigh › Neighborhood analysis of tumor and DCIS regions ↔ R/PlotInteractionMatrix.R, the whole file · a weak match · score 0.80 · plotInteractionMatrix, computeSpatialInteractionMatrix, focal clusters, row scaled, neighboring clusters, interactions
  14. [14] § Materials and methods › Analysis of human breast cancer Xenium dataset using SpNeigh › Neighborhood analysis of tumor and DCIS regions ↔ R/PlotInteractionMatrix.R, the whole file · a weak match · score 0.80 · PlotInteractionMatrix, ComputeSpatialInteractionMatrix, focal clusters, row scaled, neighboring clusters, interactions
  15. [15] § Materials and methods › Analysis of human breast cancer Xenium dataset using SpNeigh › Neighborhood analysis of tumor and DCIS regions ↔ source_code_to_reproduce_figures/02_vignette_HumanBreastCancerXenium.Rmd, lines 217–231 · score 0.76 · human breast cancer, PlotStatsPie, plot_donut, StatsCellsInside, DCIS, ring
  16. [16] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial enrichment index ↔ R/ComputeSpatialEnrichmentIndex.R, lines 1–103 · score 0.75 · avoid division, spatial enrichment, normalized SEI, zero, unweighted, gene expression
  17. [17] § Results › Overview of the SpNeigh framework ↔ R/ComputeSpatialInteractionMatrix.R, the whole file · a weak match · score 0.75 · neighboring cluster identities, spatial interaction matrix, focal cluster, nearest neighbors, tabulating, rings
  18. [18] § Results › Overview of the SpNeigh framework ↔ R/ComputeSpatialInteractionMatrix.R, the whole file · a weak match · score 0.75 · neighboring cluster identities, spatial interaction matrix, focal cluster, nearest neighbors, tabulating, rings
  19. [19] § Materials and methods › Analysis of mouse brain Visium HD dataset using SpNeigh ↔ R/GetCellsInside.R, the whole file · a weak match · score 0.74 · Cells located inside, getRingRegion, getCellsInside, getBoundary, mouse brain, spatial boundaries
  20. [20] § Materials and methods › Analysis of mouse brain Visium HD dataset using SpNeigh ↔ R/GetCellsInside.R, the whole file · a weak match · score 0.74 · Cells located inside, GetRingRegion, GetCellsInside, GetBoundary, mouse brain, spatial boundaries
  21. [21] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial neighborhood interaction matrix ↔ R/ComputeSpatialInteractionMatrix.R, the whole file · a weak match · score 0.74 · neighborhood interaction matrix, cluster identities, cell clusters, spatial neighbors, NN, nearest
  22. [22] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial neighborhood interaction matrix ↔ R/ComputeSpatialInteractionMatrix.R, the whole file · a weak match · score 0.74 · neighborhood interaction matrix, cluster identities, cell clusters, spatial neighbors, NN, nearest
  23. [23] § Materials and methods › Benchmarking differential expression and spatial modeling in SpNeigh ↔ source_code_to_reproduce_figures/01_vignette_MouseBrainXenium.Rmd, lines 649–679 · score 0.72 · mouse brain Xenium, Spearman correlation, normalized SEI, RunSpatialDE, spatial enrichment, ranked
  24. [24] § Results › Overview of the SpNeigh framework ↔ R/RunDE.R, lines 147–265 · score 0.72 · smooth function, runLimmaDE, runSpatialDE, Bayes, fits, linear
  25. [25] § Results › Overview of the SpNeigh framework ↔ R/RunDE.R, lines 147–265 · score 0.72 · smooth function, RunLimmaDE, RunSpatialDE, Bayes, fits, linear
  26. [26] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 253–321 · score 0.70 · concave hull algorithm, spatial boundaries, DBSCAN, subregions, smoothed, filtering
  27. [27] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 133–201 · score 0.70 · concave hull algorithm, spatial boundaries, DBSCAN, subregions, smoothed, filtering
  28. [28] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 1–73 · score 0.67 · local density, remove spatial outliers, nearest neighbor, NN, distance, boundaries
  29. [29] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 1–73 · score 0.67 · local density, remove spatial outliers, nearest neighbor, NN, distance, boundaries
  30. [30] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 1–73 · score 0.67 · NN distance, spatial outliers, nearest neighbor, threshold, boundary, cell
  31. [31] § Materials and methods › SpNeigh framework for spatial neighborhood modeling › Spatial boundary detection and outlier removal ↔ R/GetBoundary.R, lines 1–73 · score 0.67 · NN distance, spatial outliers, nearest neighbor, threshold, boundary, cell
  32. [32] § Results › SpNeigh reveals immune microenvironment differences between breast tumor and DCIS neighborhoods ↔ R/PlotInteractionMatrix.R, the whole file · a weak match · score 0.66 · row scaled heatmap, spatial interaction matrices, computeSpatialInteractionMatrix, proximity, populations, neighborhoods
  33. [33] § Results › SpNeigh reveals immune microenvironment differences between breast tumor and DCIS neighborhoods ↔ R/PlotInteractionMatrix.R, the whole file · a weak match · score 0.66 · row scaled heatmap, spatial interaction matrices, ComputeSpatialInteractionMatrix, proximity, populations, neighborhoods
  34. [34] § Materials and methods › Analysis of mouse brain Xenium dataset using SpNeigh ↔ R/ComputeWeights.R, lines 101–225 · score 0.66 · splitBoundaryPolyByAnchor, computeBoundaryWeights, boundary polygon, segmented, edges, spatial weights
  35. [35] § Materials and methods › Analysis of mouse brain Xenium dataset using SpNeigh ↔ R/ComputeWeights.R, lines 93–212 · score 0.66 · SplitBoundaryPolyByAnchor, ComputeBoundaryWeights, boundary polygon, segmented, edges, spatial weights
  36. [36] § Materials and methods › Analysis of human breast cancer Xenium dataset using SpNeigh › Differential expression and spatial modeling of tumor and DCIS cells ↔ R/ComputeSpatialEnrichmentIndex.R, lines 1–103 · score 0.66 · normalized SEI scores, computeCentroidWeights, gene expression, spatial weights, enriched, cells
  37. [37] § Materials and methods › Analysis of human breast cancer Xenium dataset using SpNeigh › Differential expression and spatial modeling of tumor and DCIS cells ↔ R/ComputeSpatialEnrichmentIndex.R, the whole file · a weak match · score 0.66 · normalized SEI scores, ComputeCentroidWeights, gene expression, spatial weights, enriched, cells
  38. [38] § Results › SpNeigh reveals intermediate cell populations at brain region boundaries in mouse cortex ↔ source_code_to_reproduce_figures/01_vignette_MouseBrainXenium.Rmd, lines 347–365 · score 0.65 · mouse brain Xenium, Slc17a7, RunLimmaDE, cells inside, ring, gene
  39. [39] § Results › SpNeigh reveals intermediate cell populations at brain region boundaries in mouse cortex ↔ inst/script/generate_vignette_data.R, the whole file · a weak match · score 0.65 · remove low quality, quality cells, mouse brain Xenium, Genomics, tiny, Seurat
  40. [40] § Results › SpNeigh reveals gene expression changes along spatial gradients of liver zonation ↔ source_code_to_reproduce_figures/03_vignette_HumanHealthyLiverMERFISH.Rmd, lines 402–436 · score 0.59 · COL1A1, CYP2E1, GLS2, liver, hepatocyte, MERFISH

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

R · 328 lines · 11 KB · GPL-3.0 · 5 matches

  1. #' Differential expression analysis between two groups of cells using limma
  2. #'
  3. #' Performs differential expression analysis between two groups of cells
  4. #' using the `limma` linear modeling framework.
  5. #' Supports optional observation-level weights (e.g., spatial weights)
  6. #' and filters genes by minimum expression threshold across groups.
  7. #'
  8. #' @param exp_mat A normalized gene expression matrix (genes x cells),
  9. #' either a `matrix` or `dgCMatrix`.
  10. #' Typically log-normalized counts, e.g., from a Seurat object.
  11. #' @param cells_reference A character vector of cell IDs to use as the
  12. #' reference (baseline) group.
  13. #' @param cells_target A character vector of cell IDs to use as the
  14. #' target (comparison) group.
  15. #' @param weights Optional numeric vector of observation-level weights.
  16. #' Must be named with cell IDs and
  17. #' match the length of `cells_reference + cells_target`.
  18. #' @param adj_p.value Adjusted p-value threshold for reporting
  19. #' differentially expressed genes. Default is `0.05`.
  20. #' @param min.pct Minimum proportion of cells expressing the gene in
  21. #' either group (values between 0 and 1).
  22. #' Genes not meeting this threshold are excluded before testing.
  23. #' Default is `0`.
  24. #'
  25. #' @return A data frame with differentially expressed genes,
  26. #' sorted by absolute log fold change.
  27. #' Includes columns:
  28. #' \describe{
  29. #' \item{logFC}{Log2 fold change of expression (target vs. reference)}
  30. #' \item{AveExpr}{Average expression across both groups}
  31. #' \item{t, P.Value, adj.P.Val, B}{Statistical results from `limma`}
  32. #' \item{pct.reference}{Proportion of reference cells expressing the gene}
  33. #' \item{pct.target}{Proportion of target cells expressing the gene}
  34. #' \item{gene}{Gene name (rownames from `exp_mat`)}
  35. #' }
  36. #'
  37. #' @export
  38. #'
  39. #' @examples
  40. #' # Load coordinates and log-normalized expression data
  41. #' coords <- readRDS(system.file("extdata", "MouseBrainCoords.rds",
  42. #' package = "SpNeigh"
  43. #' ))
  44. #' logNorm_expr <- readRDS(system.file("extdata", "LogNormExpr.rds",
  45. #' package = "SpNeigh"
  46. #' ))
  47. #'
  48. #' # Subset cells from cluster 0 and 2
  49. #' cells_ref <- subset(coords, cluster == 0)$cell
  50. #' cells_tar <- subset(coords, cluster == 2)$cell
  51. #'
  52. #' # Run differential expression with minimum expression threshold
  53. #' tab <- runLimmaDE(
  54. #' exp_mat = logNorm_expr,
  55. #' cells_reference = cells_ref,
  56. #' cells_target = cells_tar,
  57. #' min.pct = 0.25
  58. #' )
  59. #'
  60. #' head(tab[, c("gene", "logFC", "adj.P.Val", "pct.reference", "pct.target")])
  61. #'
  62. runLimmaDE <- function(
  63. exp_mat = NULL,
  64. cells_reference = NULL,
  65. cells_target = NULL,
  66. weights = NULL,
  67. adj_p.value = 0.05,
  68. min.pct = 0) {
  69. # --- Input checks ---
  70. if (is.null(exp_mat) || !inherits(exp_mat, c("matrix", "dgCMatrix"))) {
  71. stop(
  72. "'exp_mat' must be a numeric",
  73. " matrix or dgCMatrix (genes x cells)."
  74. )
  75. }
  76. if (is.null(cells_reference) || is.null(cells_target)) {
  77. stop("Both 'cells_reference' and 'cells_target' must be provided.")
  78. }
  79. all_cells <- c(cells_reference, cells_target)
  80. if (!all(all_cells %in% colnames(exp_mat))) {
  81. stop("Some cell IDs not found in column names of 'exp_mat'.")
  82. }
  83. if (!is.null(weights)) {
  84. if (is.null(names(weights)) || length(weights) != length(all_cells)) {
  85. stop(
  86. "'weights' must be a named numeric vector",
  87. " with the same length as all selected cells."
  88. )
  89. }
  90. weights <- weights[all_cells] # ensure correct order
  91. }
  92. # --- Convert to sparse matrix if needed ---
  93. if (inherits(exp_mat, "matrix")) {
  94. exp_mat <- Matrix::Matrix(exp_mat, sparse = TRUE)
  95. }
  96. # --- Subset expression matrix ---
  97. expr <- exp_mat[, all_cells, drop = FALSE]
  98. # --- Compute percentage of expressing cells ---
  99. df_pct <- data.frame(
  100. pct.reference = Matrix::rowMeans(expr[, cells_reference] > 0),
  101. pct.target = Matrix::rowMeans(expr[, cells_target] > 0)
  102. )
  103. rownames(df_pct) <- rownames(expr)
  104. # --- Filter genes ---
  105. keep_genes <- rowSums(df_pct >= min.pct) >= 1
  106. expr <- expr[keep_genes, , drop = FALSE]
  107. df_pct <- df_pct[keep_genes, , drop = FALSE]
  108. if (nrow(expr) == 0) {
  109. stop("No genes passed the 'min.pct' filter.")
  110. }
  111. # --- Build design matrix ---
  112. group <- factor(c(
  113. rep(1, length(cells_reference)),
  114. rep(2, length(cells_target))
  115. ))
  116. design <- stats::model.matrix(~group)
  117. # --- Fit model using limma ---
  118. fit <- limma::lmFit(expr, design, weights = weights)
  119. fit <- limma::eBayes(fit)
  120. tab <- limma::topTable(fit, coef = 2, number = Inf, p.value = adj_p.value)
  121. if (nrow(tab) == 0) {
  122. warning("No genes passed the adjusted p-value threshold.")
  123. return(tab)
  124. }
  125. # --- Add gene-level annotations ---
  126. tab <- cbind(tab, df_pct[rownames(tab), ])
  127. tab$gene <- rownames(tab)
  128. tab <- tab[order(abs(tab$logFC), decreasing = TRUE), ]
  129. return(tab)
  130. }
  131. #' Differential expression along spatial distance gradients using splines
  132. #'
  133. #' Performs spatially-aware differential expression (DE) analysis by
  134. #' modeling gene expression as a smooth function of a continuous
  135. #' spatial covariate (e.g., distance to a boundary or centroid).
  136. #' Natural spline basis functions are used to capture non-linear trends
  137. #' in expression relative to spatial distance.
  138. #' This method is suitable for identifying genes whose expression varies
  139. #' continuously across spatial structures.
  140. #'
  141. #' @inheritParams runLimmaDE
  142. #' @inheritParams splineDesign
  143. #' @param cell_ids A character vector of cell IDs (column names of `exp_mat`)
  144. #' used for DE analysis.
  145. #' @param spatial_distance A named numeric vector containing the spatial
  146. #' distance (or weights) for each cell.
  147. #' Must be the same length as `cell_ids`.
  148. #' Scaled distances are recommended.
  149. #'
  150. #' @return A data frame of differentially expressed genes, including:
  151. #' \describe{
  152. #' \item{AveExpr, F, P.Value, adj.P.Val}{limma differential expression
  153. #' outputs}
  154. #' \item{Z1, Z2, Z3}{Spline coefficients (Z1 typically corresponds
  155. #' to linear trend)}
  156. #' \item{gene}{Gene name (from `exp_mat`)}
  157. #' \item{trend}{"Positive" or "Negative" trend based
  158. #' on the sign of `Z1`}
  159. #' }
  160. #' The first spline coefficient (`Z1`) captures the main expression trend
  161. #' along the spatial distance.
  162. #'
  163. #'
  164. #' @export
  165. #'
  166. #' @examples
  167. #' # Load example data
  168. #' coords <- readRDS(system.file("extdata", "MouseBrainCoords.rds",
  169. #' package = "SpNeigh"
  170. #' ))
  171. #' logNorm_expr <- readRDS(system.file("extdata", "LogNormExpr.rds",
  172. #' package = "SpNeigh"
  173. #' ))
  174. #'
  175. #' # Identify cluster-specific cells and compute spatial weights
  176. #' cells_c0 <- subset(coords, cluster == 0)$cell
  177. #' bon_c0 <- getBoundary(data = coords, one_cluster = 0)
  178. #' weights <- computeBoundaryWeights(
  179. #' data = coords, cell_ids = cells_c0,
  180. #' boundary = bon_c0
  181. #' )
  182. #'
  183. #' # Run spatial DE
  184. #' result <- runSpatialDE(
  185. #' exp_mat = logNorm_expr, cell_ids = cells_c0,
  186. #' spatial_distance = weights
  187. #' )
  188. #' head(result)
  189. #'
  190. runSpatialDE <- function(
  191. exp_mat = NULL,
  192. cell_ids = NULL,
  193. spatial_distance = NULL,
  194. adj_p.value = 0.05,
  195. df = 3) {
  196. # --- Input checks ---
  197. if (is.null(exp_mat) || !inherits(exp_mat, c("matrix", "dgCMatrix"))) {
  198. stop("'exp_mat' must be a non-null numeric matrix (genes x cells).")
  199. }
  200. if (is.null(cell_ids)) {
  201. stop("'cell_ids' must be provided.")
  202. }
  203. if (!all(cell_ids %in% colnames(exp_mat))) {
  204. stop("Some cell IDs not found in column names of 'exp_mat'.")
  205. }
  206. all_cells <- cell_ids
  207. if (is.null(spatial_distance) || is.null(names(spatial_distance)) ||
  208. length(spatial_distance) != length(all_cells)) {
  209. stop(
  210. "'spatial_distance' must be a named vector, and its",
  211. " length must match the number of selected cells."
  212. )
  213. }
  214. # --- Make spatial_distance numeric and in correct order ---
  215. t1 <- as.numeric(spatial_distance[all_cells])
  216. # --- Subset expression matrix ---
  217. expr <- exp_mat[, all_cells, drop = FALSE]
  218. # --- Create spline-based design matrix ---
  219. Z <- splineDesign(t1, df = df)
  220. design <- stats::model.matrix(~Z)
  221. # --- Run limma ---
  222. fit <- limma::lmFit(expr, design)
  223. fit <- limma::eBayes(fit)
  224. tab <- limma::topTable(fit,
  225. coef = 2:(df + 1), number = Inf,
  226. p.value = adj_p.value
  227. )
  228. if (nrow(tab) == 0) {
  229. warning("No genes passed the adjusted p-value threshold.")
  230. return(tab)
  231. }
  232. # --- Annotate results ---
  233. tab$gene <- rownames(tab)
  234. tab$trend <- ifelse(tab$Z1 > 0, "Positive", "Negative")
  235. return(tab)
  236. }
  237. #' Generate an orthonormal spline-based design matrix
  238. #'
  239. #' Constructs an orthonormal design matrix from a numeric covariate
  240. #' (e.g., spatial distance) using a natural cubic spline basis.
  241. #' The output matrix can be used in linear modeling to capture smooth,
  242. #' non-linear trends along continuous variables.
  243. #'
  244. #' The first column of the resulting matrix is aligned to show
  245. #' a positive correlation with the input vector and typically captures
  246. #' the main linear or monotonic trend.
  247. #'
  248. #' @param x A numeric vector representing a continuous covariate
  249. #' (e.g., distance or pseudotime).
  250. #' @param df Integer. Degrees of freedom for the spline basis. Default is 3.
  251. #'
  252. #' @return A numeric matrix with orthonormal columns
  253. #' (same number of rows as `x`). The columns represent smoothed
  254. #' trends extracted from the spline basis. The first column is
  255. #' directionally aligned with the input vector (`x`).
  256. #'
  257. #' @importFrom splines ns
  258. #' @importFrom stats cor
  259. #'
  260. #' @export
  261. #'
  262. #' @examples
  263. #' x <- seq(0, 1, length.out = 100)
  264. #' Z <- splineDesign(x)
  265. #' cor(Z[, 1], x) # Should be > 0
  266. #'
  267. #' # Use Z in modeling
  268. #' y <- sin(2 * pi * x) + rnorm(100, sd = 0.2)
  269. #' fit <- lm(y ~ Z)
  270. #' summary(fit)
  271. splineDesign <- function(x, df = 3) {
  272. if (!is.numeric(x)) {
  273. stop("'x' must be a numeric vector.")
  274. }
  275. # Generate spline basis
  276. X <- splines::ns(as.numeric(x), df = df)
  277. # Augment matrix with intercept and original variable
  278. A <- cbind(1, x, X)
  279. # Orthonormalize via QR decomposition
  280. QR <- qr(A)
  281. r <- QR$rank
  282. R_rank <- QR$qr[seq(from = 1, to = r), seq(from = 1, to = r)]
  283. Z <- t(backsolve(R_rank, t(A), transpose = TRUE))
  284. # Remove intercept column
  285. Z <- Z[, -1]
  286. # Ensure first component is positively correlated with input
  287. if (stats::cor(Z[, 1], x) < 0) {
  288. Z[, 1] <- -Z[, 1]
  289. }
  290. return(Z)
  291. }

RunDE.R at commit a4af022, under GPL-3.0 · at the source

Overview

Authors: Jinming Cheng1,2, Pierce Kah Hoe Chow3,4, Nan Liu1,2,5,6,7
  1. Centre for Biomedical Data Science, Duke-NUS Medical School, Singapore169857, Singapore
  2. Duke-NUS AI + Medical Sciences Initiative, Duke-NUS Medical School, Singapore169857, Singapore
  3. Surgery Academic-Clinical Program, Duke-NUS Medical School, Singapore169857, Singapore
  4. Department of Hepato-pancreato-biliary and Transplant Surgery, Singapore General Hospital and National Cancer Centre Singapore, Singapore169610, Singapore
  5. Pre-hospital and Emergency Research Centre, Health Services Research and Population Health, Duke-NUS Medical School, Singapore169857, Singapore
  6. NUS Artificial Intelligence Institute, National University of Singapore, Singapore119077, Singapore
  7. Department of Biostatistics and Bioinformatics, Duke University, Durham 27710, United States
Journal: NAR genomics and bioinformatics, volume 8, issue 2, article lqag039
Dates: received 15 December 2025; accepted 18 March 2026; published online 8 April 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1093/nargab/lqag039 · PMID 41972009 · PMCID PMC13069690 · OpenAlex W4416079771
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: genetics / omics (modality), human (organism), mouse (organism), methods / tools (subfield)
Methods: Statistics, Preprocessing, Connectivity, Machine learning
MeSH: Gene Expression Profiling*, Software*, Spatial Transcriptomics*, Transcriptome*, Animals, Brain, Breast Neoplasms, Female, Humans, Liver, Mice (* major topic)
Topic: Single-cell and spatial transcriptomics (Molecular Biology, Biochemistry, Genetics and Molecular Biology), according to OpenAlex
Funding: National Medical Research Council (MOH-001067); Ministry of Health, Singapore
Citations: not cited yet (Europe PMC); 35 references in the paper

Abstract

Spatial transcriptomics technologies such as Xenium, MERFISH, and Visium HD enable high-resolution profiling of gene expression while preserving tissue architecture. However, most computational methods for spatial analysis do not explicitly model local tissue context, such as boundaries, neighborhoods, or gradients. Here, we present SpNeigh (https://github.com/jinming-cheng/SpNeigh/), an R package for spatial neighborhood analysis and spatially aware differential expression modeling. SpNeigh includes tools for boundary detection, spatial neighborhood extraction, distance-based weighting, and gradient-based statistical testing. It supports both region-based differential expression and smooth spatial modeling using spline-based regression, along with a spatial enrichment index that identifies genes enriched near defined spatial features. We demonstrate the utility of SpNeigh across multiple platforms and tissues, including mouse brain, human breast cancer, and human liver, revealing intermediate populations at tissue interfaces, immune microenvironment differences, and spatially zonated gene expression patterns. SpNeigh offers a flexible and interpretable framework for dissecting spatial gene expression dynamics in complex tissues.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repositories

Its files are read in the Code ↔ Paper reader above, with 40 matches between paragraphs and lines of code.

jinming-cheng/cheng_annotation_bmc_bioinfo

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: e304de70f45026388d9e281cf6e5bba8e4f12b4f, 17 July 2025
Languages: R (9)
Size: 17 files, 9 scripts
Software Heritage: not archived
Found in: “Data availability”
Holds: README, 9 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: Seurat (8 files), ggplot2 (7 files), edgeR (6 files), patchwork (3 files), ggpubr (2 files), circlize (1 file), ComplexHeatmap (1 file), tidyverse (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
10 files

jinming-cheng/SpNeigh

License: GPL-3.0
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: a4af022b7ad793a29c6a968326c8fc518bf64a61, 31 August 2026
Languages: R (34)
Size: 86 files, 34 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, license file, environment (DESCRIPTION), tests, continuous integration, documentation, 2 notebooks
Not found: CITATION.cff
Tools: ggplot2 (10 files), tidyverse (9 files), Seurat (5 files), SingleCellExperiment (2 files), limma (1 file), patchwork (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
36 files

Zenodo 17505217

License: GPL-3.0
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: the references
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: ggplot2 (9 files), tidyverse (9 files), Seurat (3 files), limma (1 file), patchwork (1 file)
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
  • 29 September 2026: the link answers (HTTP 200)
34 files
At the source:

jinming-cheng/Rcodes_for_figures_SpNeigh_ms

License: none: the authors keep all their rights
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Commit: 25133ffb466986cb6ec381e54d24270377eed92d, 9 May 2026
Languages: R (3)
Size: 5 files, 3 scripts
Software Heritage: not archived
Found in: “Code availability”
Holds: README, 3 notebooks
Not found: license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: ggplot2 (3 files), patchwork (3 files), Seurat (3 files), tidyverse (3 files)
Availability: 1 check, the latest on 29 September 2026: the link answers
  • 29 September 2026: the link answers
4 files

Zenodo 19109340

License: CC-BY-4.0
State: the link answers, verified on 29 September 2026
Evidence: files inventoried
Size: 1 file
Software Heritage: not checked
Found in: “Code availability”
Not found: README, license file, CITATION.cff, environment file, tests, continuous integration, documentation
Tools: ggplot2 (3 files), patchwork (3 files), Seurat (3 files), tidyverse (3 files)
Availability: 1 check, the latest on 29 September 2026: the link answers (HTTP 200)
  • 29 September 2026: the link answers (HTTP 200)
4 files

Code availability

The SpNeigh package is available at this GitHub repository: https://github.com/jinming-cheng/SpNeigh. It is also available on Zenodo: https://doi.org/10.5281/zenodo.17505217 [35]. Source code for reproducing all figures and analyses in this manuscript is publicly available on GitHub (https://github.com/jinming-cheng/Rcodes_for_figures_SpNeigh_ms) and Zenodo (https://doi.org/10.5281/zenodo.19109340).

Reproduced under the paper's license (CC BY), from the paper cited above.

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 5 repositories of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 81 scripts, each with its path and the digest of its content;
  • 40 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

Datasets cited

Data availability

In this study, we used publicly available datasets as detailed in Methods. Mouse brain tiny Xenium dataset: https://www.10xgenomics.com/datasets/fresh-frozen-mouse-brain-for-xenium-explorer-demo-1-standard. Human breast cancer Xenium dataset: https://www.10xgenomics.com/products/xenium-in-situ/preview-dataset-human-breast [1]. Cheng et al. annotation for human breast cancer Xenium dataset: https://github.com/jinming-cheng/cheng_annotation_bmc_bioinfo [12]. Human healthy liver MERFISH dataset : https://datadryad.org/stash/dataset/doi:10.5061/dryad.37pvmcvsg [13]. Mouse brain scRNA-seq dataset: GSE185862 (https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE185862) [14]. Mouse brain Visium HD dataset: https://www.10xgenomics.com/datasets/visium-hd-cytassist-gene-expression-mouse-brain-fresh-frozen.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 29 September 2026: the first record

Recorded: type, language, journal, volume, issue, pages, dates, 3 authors, 11 MeSH terms, 2 funders, 33 references.

Cite

This paper

Cheng, J., Chow, P. K. H., & Liu, N. (2026). SpNeigh: spatial neighborhood and differential expression analysis for high-resolution spatial transcriptomics. NAR genomics and bioinformatics, 8(2), lqag039. https://doi.org/10.1093/nargab/lqag039

BibTeX

@article{cheng2026spneigh,
author = {Cheng, Jinming and Chow, Pierce Kah Hoe and Liu, Nan},
title = {{SpNeigh: spatial neighborhood and differential expression analysis for high-resolution spatial transcriptomics}},
journal = {NAR genomics and bioinformatics},
year = {2026},
month = apr,
volume = {8},
number = {2},
pages = {lqag039},
publisher = {Oxford University Press},
issn = {2631-9268},
doi = {10.1093/nargab/lqag039},
url = {https://doi.org/10.1093/nargab/lqag039},
pmid = {41972009},
pmcid = {PMC13069690}
}

RIS

TY - JOUR
AU - Cheng, Jinming
AU - Chow, Pierce Kah Hoe
AU - Liu, Nan
TI - SpNeigh: spatial neighborhood and differential expression analysis for high-resolution spatial transcriptomics
T2 - NAR genomics and bioinformatics
J2 - NAR Genom Bioinform
PY - 2026
DA - 2026/04/08
VL - 8
IS - 2
SP - lqag039
SN - 2631-9268
PB - Oxford University Press
DO - 10.1093/nargab/lqag039
UR - https://doi.org/10.1093/nargab/lqag039
LA - en
ER -

CSL-JSON

{
"id": "10.1093/nargab/lqag039",
"type": "article-journal",
"title": "SpNeigh: spatial neighborhood and differential expression analysis for high-resolution spatial transcriptomics",
"container-title": "NAR genomics and bioinformatics",
"author": [
{
"family": "Cheng",
"given": "Jinming"
},
{
"family": "Chow",
"given": "Pierce Kah Hoe"
},
{
"family": "Liu",
"given": "Nan"
}
],
"container-title-short": "NAR Genom Bioinform",
"volume": "8",
"issue": "2",
"page": "lqag039",
"DOI": "10.1093/nargab/lqag039",
"PMID": "41972009",
"PMCID": "PMC13069690",
"ISSN": "2631-9268",
"publisher": "Oxford University Press",
"URL": "https://doi.org/10.1093/nargab/lqag039",
"language": "en",
"issued": {
"date-parts": [
[
2026,
4,
8
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41592-026-03194-8 [code]
Beyond benchmarking: an expert-guided consensus approach to spatially aware clustering.
Journal: Nature methods
In common: SingleCellExperiment, limma, Seurat, 3 other tools, methods / tools, genetics / omics, 7 references
[2] doi:10.1002/imt2.70163 [code]
Spatial multi-omics unveils sphingolipid metabolic reprogramming within the retinal pathological niche.
Journal: iMeta
In common: SingleCellExperiment, edgeR, limma, 7 other tools, genetics / omics, mouse, 1 reference
[3] doi:10.1016/j.isci.2026.115982 [code]
Multi-omics profiling-derived signature links cellular ecosystem to glioblastoma prognosis.
Journal: iScience
In common: edgeR, limma, circlize, 6 other tools, genetics / omics, 2 references
[4] doi:10.1016/j.xcrm.2026.102766 [code]
A longitudinal single-cell and spatial multiomic atlas of pediatric high-grade glioma.
Journal: Cell reports. Medicine
In common: SingleCellExperiment, edgeR, limma, 7 other tools, genetics / omics, 1 reference
[5] doi:10.1101/gr.281113.125 [code]
Single-nucleus multiomic profiling of the aging mouse substantia nigra reveals conserved gene alterations linked to Parkinson's disease.
Journal: Genome research
In common: edgeR, limma, circlize, 6 other tools, genetics / omics, mouse, 2 references
[6] doi:10.1016/j.isci.2026.115573 [code]
Female cortical cellular mosaicism underlies shared MeCP2 and PCB impacted gene pathways.
Journal: iScience
In common: SingleCellExperiment, edgeR, limma, 7 other tools, mouse
[7] doi:10.1186/s13073-026-01704-z [code]
Gene expression profiling enables refined parcellation of cortical layers in the heterogeneous human cerebral cortex.
Journal: Genome medicine
In common: SingleCellExperiment, ComplexHeatmap, Seurat, 4 other tools, genetics / omics, mouse, 4 references
[8] doi:10.1038/s41593-026-02367-0 [code]
A reproducible three-dimensional model of human brain tissue to investigate physiological and disease-associated microglia phenotypes.
Journal: Nature neuroscience
In common: SingleCellExperiment, edgeR, limma, 7 other tools
[9] doi:10.1016/j.cpblue.2026.100007 [code]
An integrated single-cell and spatial proteotranscriptomics atlas of fibroblast-driven immunoregulation within the human adult oral cavity.
Journal: Cell press blue
In common: SingleCellExperiment, edgeR, limma, 7 other tools
[10] doi:10.1038/s42003-026-10034-0 [code]
Region- and cell type-specific changes in gene expression in the cerebellum after classical fear conditioning.
Journal: Communications biology
In common: SingleCellExperiment, limma, circlize, 5 other tools, genetics / omics, mouse, 2 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.