Pixel-level background normalisation (bgnorm) for a QPTIFFImage
Source:R/bgnorm_pixels.R
bgnorm_pixels.RdFits a three-component Gaussian Mixture Model (GMM) to the log2-transformed
pixel intensities for each channel in a QPTIFFImage and
deconvolves the biological signal component from background sources. All
channels are processed independently; use channels to restrict
processing to a subset. Optionally runs channels in parallel via
BiocParallel.
Usage
bgnorm_pixels(
img,
channels = NULL,
cofactor = 150,
quantile_norm = FALSE,
quantile = 0.75,
sample_prop = 0.1,
BPPARAM = BiocParallel::SerialParam(),
...
)Arguments
- img
A
QPTIFFImage[H x W x C]. Useas.QPTIFFImageto promote a plain 3-D array or 2-D matrix.- channels
Character or integer vector of channels to process, or
NULL(default) to process all channels.- cofactor
Positive numeric cofactor for the log2 transform. Default 150 is appropriate for 16-bit Akoya PhenoCycler-Fusion images.
- quantile_norm
Logical; apply model-based quantile normalisation (bgnormQ)? Default
FALSE.- quantile
Quantile of the signal component used for normalisation when
quantile_norm = TRUE. Default 0.75.- sample_prop
Numeric in (0, 1]; proportion of non-zero pixels used to fit the GMM. Values < 1 draw a random subset, accelerating fitting on large images. Default
1(all non-zero pixels).- BPPARAM
A
BiocParallelParaminstance. DefaultBiocParallel::SerialParam().- ...
Additional arguments forwarded to the internal GMM fitter.
Value
A QPTIFFImage [H x W x C] of background-adjusted
log-intensities. The per-channel BgnormResult objects
(GMM parameters, JSD) are stored as an attribute; retrieve
them with bgnorm_results(result).
Details
The preprocessing, model, and deconvolution steps follow Kharbanda et al. 2025:
Log2-transform: \(I_{\log} = \log_2(I/c + 1)\).
Fit a 3-component GMM via EM (mclust), filtering zeros and optionally subsampling for speed.
Resolve component identities (background, non-specific, signal).
Apply the deconvolution formula to recover \(U_3\).
Optionally normalise by the 75th-percentile of the signal component (bgnormQ).
Examples
set.seed(42)
px <- c(exp(rnorm(500, log(50), 0.4)),
exp(rnorm(400, log(300), 0.6)),
exp(rnorm(100, log(2000), 1.0)))
arr <- array(c(px, px), dim = c(length(px), 1L, 2L),
dimnames = list(NULL, NULL, c("DAPI", "CD3")))
img <- as.QPTIFFImage(arr)
res <- bgnorm_pixels(img)
#> Sampling not required: using all 1000 non-zero pixels for GMM fitting.
#> Sampling not required: using all 1000 non-zero pixels for GMM fitting.
names(res) # channel names of the adjusted image
#> [1] "DAPI" "CD3"
bgnorm_results(res)[["DAPI"]] # BgnormResult for the DAPI channel
#> BgnormResult (pixel-level)
#> n = 1000
#> Component means: 0.415 1.516 4.248
#> JSD (QC metric): 0.722
#> BIC (G=2): -2.34 BIC (G=3): -2.04
#> No signal detected: FALSE
#> Quantile normalised: FALSE
#> Tissue positivity: 17.4%
# Process only selected channels
res2 <- bgnorm_pixels(img, channels = "DAPI")
#> Sampling not required: using all 1000 non-zero pixels for GMM fitting.
# \donttest{
# Real tissue image shipped with the package
path <- system.file("extdata", "PA_HNC_sample.ome.tiff", package = "bgnormR")
img <- read_qptiff(path)
#> Reading TIFF directory structure ...
#> Reading OME-TIFF metadata ...
#> Reading IFD page layouts ...
#> Loading 5 channel(s) ...
#> Loading 5 channel(s) ...
res <- bgnorm_pixels(img, sample_prop = 0.1)
bgnorm_results(res)[["PanCK"]] # per-channel model summary
#> BgnormResult (pixel-level)
#> n = 440000
#> Component means: 0.031 0.163 1.882
#> JSD (QC metric): 0.8827
#> BIC (G=2): -1.69 BIC (G=3): -1.4
#> No signal detected: FALSE
#> Quantile normalised: FALSE
#> Tissue positivity: 68.3%
# }