Skip to contents

this provides an R package which implements a spatial correlation metric originally designed for analysis of spatial transcriptomics data.

installation

to install the package, the package archive uploaded in the latest GitHub release (which is generated via an automated workflow) can be used.

[!IMPORTANT] installing the package from source requires having installed a toolchain for the Rust programming language

this can be done using the withr and pak R packages via the following R snippet:

withr::with_envvar(
  c(RUSTFLAGS = "-C target-cpu=native"),
  pak::pak("url::https://github.com/goeva-lab/usci/releases/latest/download/usci.tar.gz")
)

usage

the usci package provides two key functions: usci and asci.

metric definition

usci computes a spatial correlation metric c between two observations sets, where each observation has a value and a set of spatial coordinates, defined as:

c = \sqrt{N_A} * \sqrt{N_B} * \frac{ \sum_{i \in A} \sum_{j \in B} ( e^{\frac{-d(i, j)}{s}} * (A_i - \overline{A}) * (B_j - \overline{B}) ) }{ (\sum_{i \in A} \sum_{j \in B} e^{\frac{-d(i, j)}{s}}) * \sqrt{\sum_{i \in A} A_i} * \sqrt{\sum_{j \in B} B_j} }

where:

  • N_A represents the size of observation set A
  • d(i, j) represents the euclidean distance between observations i and j
  • A_i represents the value of observation i in observation set A
  • \overline{A} represents the mean value across all values in observation set A
  • s represents a scale factor

asci approximation

from the definition of c, we can see that computing c is O(N_A * N_B), e.g. quadratic over total input size.

because of this, the usci package also provides the asci function, which attempts to return an approximation of c by, for each observation in A, only evaluating the values for observations in B s.t. the spatial weight term e^{\frac{-d(i, j)}{s}} \geq \epsilon (where \epsilon is the allowed error term, by default set to 1e-8). reformulating this bound, we see that this can be rephrased as d(i, j) \leq -ln(\epsilon) * s, meaning that it heavily depends on the value of the scale factor. for scale factor values where this bound allows excluding a nontrivial fraction of observations, it allows for an order of magnitude speed up in runtime while causing only a marginal drift in accuracy.

using asci requires first computing a spatial index for the observation set B, via the provided build_index function.

example

a demonstration of package use can be seen below:

library(usci)

a_n <- 128
b_n <- 256

a <- rpois(a_n, runif(1, 0, 32))
a_x <- rnorm(a_n)
a_y <- rnorm(a_n)

b <- rpois(b_n, runif(1, 0, 32))
b_x <- rnorm(b_n)
b_y <- rnorm(b_n)

c <- usci(a, b, a_x, a_y, b_x, b_y, 1e-1)

b_idx <- build_index(b_x, b_y)
c_approx <- asci(a, b, a_x, a_y, b_idx, 1e-1)

parallelism

by default, all computations in the library are performed in a sequential manner. however, parallelism is supported using the rayon library. to enable this, the set_par function is provided, which after being called enables the use of parallelized implementations of numerical routines across all package functions.

development

this repository purposefully does not check in any generated scaffolding, including those by rextendr. as such, to get a local development setup properly initialized, the following commands need to be run:

echo '# Generated by roxygen2: do not edit by hand' > ./NAMESPACE
R -q -e 'rextendr::update_scaffold()'
chmod +x ./configure
chmod +x ./cleanup
R -q -e 'roxygen2::roxygenize()'