Skip to content

combat

combat

combat(
    data,
    batch="imageid",
    layer="raw",
    log=True,
    replaceOriginal=False,
    label="combat",
    chunkSize=10000,
    maxWorkers=None,
    verbose=True,
    outputDir=None,
    streamData=False,
    sdataTable=None,
)

ComBat batch correction across images or any other batch variable.

Wraps pycombat to remove additive and multiplicative batch effects while preserving biological variation. The typical use is correcting slide-to-slide staining differences before pooling samples.

By default the corrected matrix is written to layers[label] and the original is left alone; replaceOriginal=True writes it into .X instead. The matrix is assembled with Polars, and the optional log1p step runs in parallel chunks.

At least two batches are required

A single-image object raises an Exception — there is nothing to correct between.

Parameters:

Name Type Description Default
data (AnnData | SpatialData | str, required)

The cell table. An AnnData, a path to an .h5ad file, a SpatialData object, or a path to a .zarr SpatialData store.

required
batch str

Column in obs identifying the batch. Usually the image or slide id.

'imageid'
layer str

Which matrix to correct. 'raw' uses .raw.X, None uses .X, any other string names a key in .layers.

'raw'
log bool

Apply log1p before correcting. ComBat assumes roughly Gaussian data, so leave this on for raw intensities.

True
replaceOriginal bool

Write the corrected matrix into .X instead of layers[label].

False
label str

Layer the corrected matrix is written to when replaceOriginal=False.

'combat'
chunkSize int

Rows per chunk for the parallel log1p step.

10000
maxWorkers int

Threads for the log1p step. Defaults to max(1, cpu_count() - 1).

None
verbose bool

Print progress messages.

True
outputDir str

Directory to write the updated object to. With None the object is returned instead.

None
streamData bool

Run out of core against an .h5ad path with CAP-AnnData, reading only the sections this function needs and writing back only what it changes. Requires data to be a path; the file is updated in place and None is returned.

False
sdataTable str

Which SpatialData table to work on. Ignored for AnnData input, and optional when the store has exactly one table.

None

Returns:

Name Type Description
adata AnnData | SpatialData | None

The updated object with the corrected matrix in layers[label], or in .X when replaceOriginal=True. None in streaming mode.

Raises:

Type Description
Exception

When batch has fewer than two distinct values.

Example
adata = sp.pp.combat(adata, batch="imageid")

# Compare before and after.
sp.pl.heatmap(adata, groupBy="imageid", layer=None)
sp.pl.heatmap(adata, groupBy="imageid", layer="combat")

# Correct in place, using a slide column rather than the image id.
adata = sp.pp.combat(adata, batch="slide", replaceOriginal=True)