Estimate a steady-state molecular concentration field
Source:R/estimate_concentration_field.R
estimate_concentration_field.RdSolves the screened Poisson (diffusion-clearance) PDE over a spatial mask to produce a continuous concentration field from discrete transcript or protein detection coordinates:
Usage
estimate_concentration_field(
mask,
transcript_coords,
D = 1,
lambda = 0.1,
production_rate = 1,
diffusion_length = NULL,
weight_col = NULL,
method = "fd",
grid_resolution = 256L,
boundary_condition = "dirichlet",
fd_solver = "direct",
sor_omega = 1.7,
sor_tol = 1e-06,
sor_max_iter = 1500L,
green_r_min_factor = 0.5,
kde_bandwidth = NULL,
include_external = FALSE,
normalize = FALSE,
log_transform = FALSE,
clip_negative = TRUE,
n_cores = 1L,
return_sources = TRUE,
plot = FALSE,
verbose = TRUE
)Arguments
- mask
An
sfcorsfpolygon object defining the tissue boundary. Typically the output ofTissueMask::fit_spatial_mask(). Multi-polygon objects (holes, islands) are supported.- transcript_coords
A
data.frameor matrix with columnsxandy(or first two columns used if names differ) giving transcript or detection coordinates in the same coordinate system asmask.- D
Diffusion coefficient (arbitrary spatial units squared per time). Controls the amplitude of the field (\(C \propto 1/D\)); the spatial pattern depends only on
diffusion_length. Default1.0.- lambda
First-order clearance rate. Must be
> 0unlessdiffusion_lengthis supplied. Default0.1.- production_rate
Scalar multiplier applied to all source weights. If
weight_colisNULLeach transcript contributesproduction_rateunits of source strength. Default1.0.- diffusion_length
Optional. If supplied, overrides
Dandlambdaand sets \(L\) directly. Useful for sweeping the spatial scale without changing amplitude.- weight_col
Optional character string naming a column in
transcript_coordsto use as per-transcript weights (e.g."umi"). Weights are multiplied byproduction_rate.- method
Solver. One of:
"fd"Finite-difference sparse linear system (default). Supports exact Dirichlet or Neumann boundary conditions. Recommended for most use cases.
"green"FFT convolution with the analytic 2-D Green's function \(K_0(\kappa r)\). Ignores domain boundary; fast for parameter sweeps.
"kde"Gaussian kernel density estimate. Phenomenological baseline; no physical boundary conditions.
- grid_resolution
Integer. Number of grid cells per axis (the grid is
grid_resolution x grid_resolution). Default256L.- boundary_condition
"dirichlet"(concentration zero at boundary) or"neumann"(zero normal flux; molecules reflected). Only applies whenmethod = "fd". Default"dirichlet".- fd_solver
"direct"(LU factorisation viaMatrix::solve()) or"iterative"(red-black SOR). Direct is exact and fast forgrid_resolution <= 400; iterative avoids the dense LU at very high resolution. Only applies whenmethod = "fd". Default"direct".- sor_omega
SOR relaxation parameter (0 < omega < 2). Default
1.7.- sor_tol
Convergence tolerance for SOR. Default
1e-6.- sor_max_iter
Maximum SOR iterations. Default
1500L.- green_r_min_factor
Regularisation for the Green's function singularity at r = 0; sets r_min = green_r_min_factor * h. Default
0.5.- kde_bandwidth
Bandwidth for the KDE smoother. Defaults to
Lwhenmethod = "kde".- include_external
Logical. If
TRUE, transcripts outsidemaskare included as sources. DefaultFALSE.- normalize
Logical. If
TRUE, rescales the field to[0, 1]after solving. DefaultFALSE.- log_transform
Logical. If
TRUE, applieslog1p()to the field after solving (and afterclip_negative). DefaultFALSE.- clip_negative
Logical. If
TRUE, sets small negative values (solver artefacts) to zero. DefaultTRUE.- n_cores
Integer. Number of cores for mask rasterisation. Parallel rasterisation is available on Unix-like systems only. Default
1L.- return_sources
Logical. Include the binned source density matrix in the return value. Default
TRUE.- plot
Logical. If
TRUEandggplot2is installed, print a quick field plot. DefaultFALSE.- verbose
Logical. Print progress messages. Default
TRUE.
Value
A named list with elements:
fieldN x Nnumeric matrix;NAoutside the mask.x,yGrid centre coordinates (length
Neach).hx,hyGrid cell width and height.
maskN x Nlogical matrix (TRUE= inside mask).sourcesN x Nbinned source density (orNULLwhenreturn_sources = FALSE).paramsList of all resolved input parameters.
diagnosticsTiming and cell/transcript counts.
Details
$$D \nabla^2 C(\mathbf{x}) - \lambda C(\mathbf{x}) + s(\mathbf{x}) = 0$$
The key derived quantity is the diffusion length \(L = \sqrt{D/\lambda}\),
which sets the characteristic decay distance from each source. Three solvers
are available: "fd" (finite-difference, recommended), "green" (Green's
function via FFT), and "kde" (Gaussian kernel density, phenomenological).
Examples
library(sf)
#> Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
set.seed(1)
sq <- st_polygon(list(cbind(c(0,10,10,0,0), c(0,0,10,10,0))))
mask <- st_sfc(sq)
tc <- data.frame(x = runif(80, 1, 9), y = runif(80, 1, 9))
res <- estimate_concentration_field(mask, tc, D = 1, lambda = 0.2,
grid_resolution = 64L, verbose = FALSE)
str(res$field)
#> num [1:64, 1:64] NA NA NA NA NA NA NA NA NA NA ...