Skip to content

Python API

The pure-compute layer of napari-colocalization is independent of napari and Qt - you can import the metric, masking, and analysis functions from a script or notebook and use them on plain ndarrays.

Documentation index: Home · Usage · Metrics · Python API

The function reference below is generated directly from the source docstrings. The narrative and examples on this page are written by hand; the ::: blocks are filled in automatically by mkdocstrings at build time.

Module layout

napari_colocalization
├── _metrics.py     pearson, spearman, li_icq, manders, overlap,
│                   costes_threshold, costes_regression
├── _masking.py     shapes_to_label_mask, labels_to_label_mask, iter_regions
├── _analysis.py    analyse_pairwise, analyse_all_to_all, COLUMNS
├── _diagnostics.py costes_randomization, van_steensel_ccf, li_ica
├── _objects.py     label_objects, object_table, object_centroids,
│                   nearest_neighbour_vectors
├── _sample_data.py make_sample_data, make_sample_data_3d,
│                   make_sample_data_cbs006rbm, make_sample_data_coloc
└── _widget.py      ColocalizationWidget (Qt-only)

The leading underscore is a convention from the napari plugin template; the symbols below are stable and intended to be imported.

Metrics - napari_colocalization._metrics

Pure-numpy colocalization metrics.

No napari / qtpy imports here - every function in this module operates on ndarrays so it can be tested headlessly and reused from scripts. PCC and Manders delegate to scikit-image; SRCC uses scipy.stats; Costes auto-threshold is implemented locally because scikit-image does not provide it.

pearson

pearson(a, b, mask=None)

Pearson correlation coefficient and two-tailed p-value.

Wraps skimage.measure.pearson_corr_coeff. Returns (nan, nan) for inputs with fewer than two samples or zero variance in either channel - both edge cases for which PCC is mathematically undefined.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

b

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

mask

Boolean array with the same shape as a/b. Only pixels where mask is True are included in the calculation. None (the default) uses every pixel.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
pcc

The Pearson correlation coefficient in [-1, 1], or nan if the inputs are degenerate.

TYPE: float

p_value

Two-tailed p-value for the null hypothesis that the coefficient is zero. nan if pcc is nan.

TYPE: float

Examples:

>>> import numpy as np
>>> from napari_colocalization._metrics import pearson
>>> rng = np.random.default_rng(0)
>>> a = rng.random((64, 64))
>>> pearson(a, a)[0]
1.0

spearman

spearman(a, b, mask=None)

Spearman rank correlation coefficient and p-value.

Uses scipy.stats.spearmanr on the masked, flattened intensities. Robust to monotonic non-linearity and outliers.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

b

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

mask

Boolean array with the same shape as a/b. Only pixels where mask is True are included in the calculation.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
rho

Spearman's rank correlation coefficient in [-1, 1], or nan if the inputs are degenerate (fewer than two samples, or zero variance in either channel).

TYPE: float

p_value

Two-tailed p-value for the rank correlation, or nan.

TYPE: float

Examples:

>>> import numpy as np
>>> from napari_colocalization._metrics import spearman
>>> a = np.linspace(0.1, 10.0, 1000)
>>> spearman(a, a ** 3)[0]    # monotonic non-linear
1.0

li_icq

li_icq(a, b, mask=None)

Li's Intensity Correlation Quotient (ICQ).

For each pixel i, form the covariance contribution P_i = (a_i - mean(a)) * (b_i - mean(b)). The ICQ is the fraction of pixels for which this product is positive, re-centred to lie on [-0.5, 0.5]:

.. math:: \mathrm{ICQ} = \frac{|{i : P_i > 0}|}{N} - 0.5

Following Li et al. (2004), values close to +0.5 indicate dependent (co-varying) staining, 0 indicates random staining, and -0.5 indicates segregated (anti-varying) staining.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

b

Same-shape intensity arrays of any dimensionality.

TYPE: array_like

mask

Boolean array with the same shape as a / b. Only pixels where mask is True are counted. None (the default) uses every pixel.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
icq

Value in [-0.5, 0.5], or nan for inputs with fewer than two samples or zero variance in either channel (where the means coincide with every value and the sign of P_i is degenerate).

TYPE: float

Notes

Pixels with P_i == 0 (typically because one channel equals its mean exactly at that pixel) are excluded from the fraction's numerator and denominator, mirroring the convention adopted by ImageJ's Coloc 2 plugin.

References

Li, Q. et al. (2004). A Syntaxin 1, Galpha(o), and N-type Calcium Channel Complex at a Presynaptic Nerve Terminal: Analysis by Quantitative Immunocolocalization. J. Neurosci. 24(16), 4070-4081.

Examples:

>>> import numpy as np
>>> from napari_colocalization._metrics import li_icq
>>> rng = np.random.default_rng(0)
>>> a = rng.random((128, 128))
>>> round(li_icq(a, a), 2)         # perfectly co-varying
0.5
>>> round(li_icq(a, -a), 2)        # perfectly anti-varying
-0.5

manders

manders(a, b, threshold_a, threshold_b, mask=None)

Manders' colocalization coefficients M1 and M2.

M1 is the fraction of the channel-A intensity that lies in pixels where channel B is above threshold_b. M2 is the symmetric counterpart for channel B above threshold_a. Asymmetry between the two is meaningful - it reflects the difference in how much of each channel co-occurs with the other.

Wraps skimage.measure.manders_coloc_coeff, which expects a binary mask for the second image; we threshold internally and then call it twice.

PARAMETER DESCRIPTION
a

Same-shape, non-negative intensity arrays.

TYPE: array_like

b

Same-shape, non-negative intensity arrays.

TYPE: array_like

threshold_a

Per-channel thresholds. Use costes_threshold to derive them automatically, or pass values you have set manually.

TYPE: float

threshold_b

Per-channel thresholds. Use costes_threshold to derive them automatically, or pass values you have set manually.

TYPE: float

mask

Boolean array selecting the analysed region. None analyses every pixel.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
m1, m2 : float

Each in [0, 1], or nan if the analysed region contains no positive intensity in either channel.

Examples:

>>> import numpy as np
>>> from napari_colocalization._metrics import manders
>>> a = np.zeros((10, 10)); a[:, :] = 1.0
>>> b = np.zeros((10, 10)); b[:5, :] = 1.0   # half of A overlaps B
>>> m1, m2 = manders(a, b, threshold_a=0.5, threshold_b=0.5)
>>> round(m1, 2), round(m2, 2)
(0.5, 1.0)

overlap

overlap(a, b, mask=None)

Manders' overlap coefficient r and split coefficients k1, k2.

These threshold-free measures (Manders et al. 1992) quantify co-occurrence from the raw intensity products, complementing the threshold-dependent M1/M2 from manders:

.. math:: r = \frac{\sum_i a_i b_i} {\sqrt{\sum_i a_i^2 \; \sum_i b_i^2}}, \quad k_1 = \frac{\sum_i a_i b_i}{\sum_i a_i^2}, \quad k_2 = \frac{\sum_i a_i b_i}{\sum_i b_i^2}

r lies in [0, 1] for non-negative intensities and is insensitive to a difference in mean brightness between the two channels. k1 and k2 split that co-occurrence per channel and are sensitive to such differences - their asymmetry is informative.

r is delegated to skimage.measure.manders_overlap_coeff. The split coefficients k1/k2 have no scikit-image equivalent (skimage.measure.manders_coloc_coeff computes the threshold-gated M1/M2 used by manders, a different quantity), so they are derived from the same intensity sums here.

PARAMETER DESCRIPTION
a

Same-shape, non-negative intensity arrays.

TYPE: array_like

b

Same-shape, non-negative intensity arrays.

TYPE: array_like

mask

Boolean array selecting the analysed region. None (the default) uses every pixel.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
r, k1, k2 : float

The overlap coefficient and the two split coefficients. Any coefficient whose denominator is zero (an all-zero channel within the region) is returned as nan; all three are nan for an empty region.

References

Manders, E.M.M. et al. (1992). Dynamics of three-dimensional replication patterns during the S-phase, analysed by double labelling of DNA and confocal microscopy. J. Cell Sci. 103, 857-862.

Examples:

>>> import numpy as np
>>> from napari_colocalization._metrics import overlap
>>> a = np.array([1.0, 2.0, 3.0, 4.0])
>>> overlap(a, a)                      # identical channels
(1.0, 1.0, 1.0)
>>> r, k1, k2 = overlap(a, 2 * a)      # b is twice a
>>> round(r, 4), round(k1, 4), round(k2, 4)
(1.0, 2.0, 0.5)

costes_threshold

costes_threshold(a, b, mask=None, max_iter=100)

Costes' iterative auto-threshold for Manders' M1 / M2.

Follows Fiji Coloc 2 (AutoThresholdRegression):

  1. Fit the costes_regression orthogonal line b = m*a + c.
  2. Step a candidate threshold by bisection. The threshold pair always lies on the line; the channel that is stepped is the one giving finer resolution - channel A when |m| < 1 (then T_b = m*T_a + c) else channel B (then T_a = (T_b - c)/m).
  3. At each candidate, compute the Pearson correlation of the below-threshold pixels (a < T_a or b < T_b). Bisect downward while that correlation is positive and upward when it is non-positive (or undefined), converging on the threshold where the background pixels stop correlating.
PARAMETER DESCRIPTION
a

Same-shape intensity arrays.

TYPE: array_like

b

Same-shape intensity arrays.

TYPE: array_like

mask

Restrict the regression and search to this region.

TYPE: array_like of bool DEFAULT: None

max_iter

Maximum bisection iterations (Coloc 2 default); the search also stops once the step falls below one intensity unit.

TYPE: int DEFAULT: 100

RETURNS DESCRIPTION
threshold_a, threshold_b : float

Per-channel thresholds for manders, clamped to the data range. Falls back to (max(a), max(b)) when the regression slope is non-positive or undefined (no co-occurrence to threshold for).

References

Costes, S.V. et al. (2004). Automatic and quantitative measurement of protein-protein colocalization in live cells. Biophys. J. 86(6), 3993-4003.

costes_regression

costes_regression(a, b, mask=None)

Orthogonal-regression line b = slope * a + intercept.

This is the line costes_threshold walks along; it is exposed separately so callers (e.g. the cytofluorogram) can draw the same line. To match Fiji's Coloc 2 we use orthogonal (total-least-squares) regression rather than an ordinary least-squares fit - the relationship is symmetric (neither channel is the independent variable), and OLS would bias the slope when the predictor channel is noisy. The slope is the principal axis of the intensity covariance:

.. math:: m = \frac{\sigma_b^2 - \sigma_a^2 + \sqrt{(\sigma_b^2 - \sigma_a^2)^2 + 4\sigma_{ab}^2}} {2\sigma_{ab}}, \quad c = \bar b - m\,\bar a

PARAMETER DESCRIPTION
a

Same-shape intensity arrays.

TYPE: array_like

b

Same-shape intensity arrays.

TYPE: array_like

mask

Restrict the regression to this region.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
slope, intercept : float

Regression coefficients, or (nan, nan) when the region has fewer than two samples, zero variance in either channel, or zero covariance (no line to fit).

References

Costes, S.V. et al. (2004). Automatic and quantitative measurement of protein-protein colocalization in live cells. Biophys. J. 86(6), 3993-4003. Implementation matched to Fiji Coloc 2 AutoThresholdRegression.

Masking - napari_colocalization._masking

Region-of-interest helpers.

These functions convert a napari Shapes or Labels layer into an integer label mask (0 = background, 1..N = regions) and iterate over the non-zero regions. The helpers duck-type the layer interface - they do not import napari - so they can be tested with simple stand-in objects.

shapes_to_label_mask

shapes_to_label_mask(shapes_layer, image_shape)

Rasterise a napari Shapes layer to an integer label mask.

Uses Shapes.to_labels(labels_shape=image_shape). The resulting mask has shape image_shape, with 0 outside any shape and 1..N inside each shape (where shape i of the layer maps to label i + 1).

PARAMETER DESCRIPTION
shapes_layer

Any object that exposes .to_labels(labels_shape=...); duck-typed so tests can pass a stand-in.

TYPE: Shapes

image_shape

The desired output shape, typically the spatial shape of the image being analysed.

TYPE: tuple of int

RETURNS DESCRIPTION
mask

Integer label image of shape image_shape.

TYPE: numpy.ndarray of int

labels_to_label_mask

labels_to_label_mask(labels_layer, image_shape)

Validate and return integer data from a napari Labels layer.

PARAMETER DESCRIPTION
labels_layer

Any object that exposes a .data attribute holding an integer ndarray.

TYPE: Labels

image_shape

The expected shape; labels_layer.data.shape must match exactly.

TYPE: tuple of int

RETURNS DESCRIPTION
mask

The label data, dtype-cast to int.

TYPE: numpy.ndarray of int

RAISES DESCRIPTION
ValueError

If the layer's data shape does not match image_shape.

iter_regions

iter_regions(label_mask)

Yield (label_id, bool_mask) for each non-zero region.

PARAMETER DESCRIPTION
label_mask

Integer label image. None is treated specially as "use the whole image".

TYPE: numpy.ndarray of int, or None

YIELDS DESCRIPTION
label_id

The integer label value (1, 2, ...). When label_mask is None, yields 0 instead.

TYPE:: int

bool_mask

Boolean mask of the same shape as label_mask, True where the label equals label_id. None when label_mask is None.

TYPE:: numpy.ndarray of bool, or None

Examples:

>>> import numpy as np
>>> from napari_colocalization._masking import iter_regions
>>> mask = np.zeros((4, 4), dtype=int)
>>> mask[:2, :2] = 1
>>> mask[2:, 2:] = 2
>>> [(label, int(m.sum())) for label, m in iter_regions(mask)]
[(1, 4), (2, 4)]

Analysis - napari_colocalization._analysis

COLUMNS is the canonical column order shared by the table, the CSV export, and the row dicts:

('region', 'slice', 'channel_a', 'channel_b', 'n_pixels',
 'pcc', 'pcc_pvalue', 'srcc', 'srcc_pvalue',
 'icq',
 'overlap', 'k1', 'k2',
 'm1', 'm2', 'threshold_a', 'threshold_b')

(slice is the plane index for per-Z-slice runs, and NaN otherwise.)

High-level orchestrators that produce a result row per region.

These accept ndarrays plus a label mask, walk every non-zero region, compute the requested metrics, and return a list of dicts suitable for direct insertion into a table or a CSV.

Failure policy: conditions that make the whole request invalid (shape mismatch, unknown options, missing manual thresholds) raise ValueError so the caller can surface the reason. Per-region degeneracies - a single ROI too small or with a constant/empty channel - are not errors in a multi-region run; the affected metrics stay NaN (a visible blank cell), and a human-readable reason is appended to the optional region_warnings collector so the caller can summarise how many regions were skipped and why.

analyse_pairwise

analyse_pairwise(a, b, *, label_mask=None, metrics=ALL_METRICS, threshold_method='costes', threshold_a=None, threshold_b=None, channel_a='A', channel_b='B', slice_axis=None, region_warnings=None)

Compute selected metrics for each region of two grayscale arrays.

Walks every non-zero region of label_mask (or analyses the whole image when label_mask is None) and computes the requested metrics within each region. Missing metrics are written as NaN so the output schema is constant.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays (2D or 3D).

TYPE: ndarray

b

Same-shape intensity arrays (2D or 3D).

TYPE: ndarray

label_mask

Integer label image (0 = background, 1..N = regions). None means analyse the whole image as one region.

TYPE: numpy.ndarray of int DEFAULT: None

metrics

Which metrics to compute. Defaults to all. 'overlap' adds the threshold-free overlap coefficient and the split coefficients k1/k2.

TYPE: sequence of {'pcc', 'srcc', 'icq', 'overlap', 'mcc'} DEFAULT: ALL_METRICS

threshold_method

Only used when 'mcc' is in metrics. 'costes' runs costes_threshold per region; 'manual' uses the values supplied below; or a per-channel auto-threshold name - one of 'otsu', 'li', 'triangle', 'yen', 'mean', 'isodata' (the skimage.filters.threshold_* family, thresholding each channel independently → Manders tM1/tM2).

TYPE: str DEFAULT: 'costes'

threshold_a

Required when threshold_method='manual'.

TYPE: float DEFAULT: None

threshold_b

Required when threshold_method='manual'.

TYPE: float DEFAULT: None

channel_a

Display names for the two channels - written into the result rows so they round-trip into the table and CSV.

TYPE: str DEFAULT: 'A' and 'B'

channel_b

Display names for the two channels - written into the result rows so they round-trip into the table and CSV.

TYPE: str DEFAULT: 'A' and 'B'

slice_axis

If given, analyse each plane along this axis separately (JACoP B's "consider Z slices separately") rather than the whole volume: every region is reported once per slice, with the plane index in the 'slice' column. A label_mask matching the full volume is sliced alongside; a slice-shaped mask is reused for every plane.

TYPE: int DEFAULT: None

region_warnings

If provided, a human-readable string is appended for each region where a requested metric could not be computed (too few pixels, or a constant/empty channel). The metric cell itself stays NaN; this is the channel for telling the user why. None (default) discards the reasons.

TYPE: list DEFAULT: None

RETURNS DESCRIPTION
rows

One row per region. Each row has the keys listed in COLUMNS.

TYPE: list of dict

RAISES DESCRIPTION
ValueError

If a and b have different shapes, or if threshold_method='manual' is given without both thresholds, or if threshold_method is unknown.

Examples:

>>> import numpy as np
>>> from napari_colocalization._analysis import analyse_pairwise
>>> rng = np.random.default_rng(0)
>>> a = rng.random((32, 32)); b = a.copy()
>>> rows = analyse_pairwise(a, b, metrics=('pcc',))
>>> rows[0]['pcc']
1.0

analyse_all_to_all

analyse_all_to_all(image, channel_axis, *, label_mask=None, metrics=ALL_METRICS, threshold_method='costes', threshold_a=None, threshold_b=None, channel_names=None, region_warnings=None)

Compute metrics for every channel pair (i, j), i < j.

Iterates over each unordered pair of channels along channel_axis and dispatches to analyse_pairwise. For N channels this produces N*(N-1)/2 × R rows, where R is the number of non-zero regions in label_mask (or 1 for the whole image).

PARAMETER DESCRIPTION
image

N-dimensional array with one channel axis. The remaining axes are spatial (the plugin supports up to 3 spatial axes, i.e. 4D total).

TYPE: ndarray

channel_axis

Axis index along which channels are enumerated.

TYPE: int

label_mask

Integer label image whose shape matches image with channel_axis removed.

TYPE: numpy.ndarray of int DEFAULT: None

metrics

Forwarded to analyse_pairwise.

TYPE: sequence of {'pcc', 'srcc', 'icq', 'overlap', 'mcc'} DEFAULT: ALL_METRICS

threshold_method

Forwarded to analyse_pairwise ('costes', 'manual', or an auto-threshold name like 'otsu'). Manual thresholds apply identically to every channel pair.

TYPE: str DEFAULT: 'costes'

threshold_a

Forwarded to analyse_pairwise.

TYPE: float DEFAULT: None

threshold_b

Forwarded to analyse_pairwise.

TYPE: float DEFAULT: None

channel_names

One name per channel along channel_axis. Defaults to ['c0', 'c1', ...].

TYPE: sequence of str DEFAULT: None

region_warnings

Forwarded to analyse_pairwise; collects per-region reasons across every channel pair.

TYPE: list DEFAULT: None

RETURNS DESCRIPTION
rows

Concatenation of the per-pair results from analyse_pairwise.

TYPE: list of dict

RAISES DESCRIPTION
ValueError

If len(channel_names) does not match the channel count.

Diagnostics - napari_colocalization._diagnostics

Curve/distribution producers behind the Diagnostics tab. Unlike the metrics, a degenerate whole input raises ValueError rather than returning NaN.

Pure-compute colocalization diagnostics.

Unlike _metrics, whose functions return a scalar per region, these produce a curve or a distribution - the payloads behind the widget's Diagnostics tab. As in _metrics there are no napari/qtpy imports here, so every function operates on ndarrays and can be tested headlessly. The scalar summaries (peak shift, ICQ, p-value) are returned alongside the arrays so the widget can drop them into a label while the arrays go to the plot.

Failure policy matches the rest of the package: a degenerate whole input (shape mismatch, too few pixels, an out-of-range parameter) raises ValueError for the widget to surface as a napari warning, rather than returning a silently meaningless result.

costes_randomization

costes_randomization(a, b, mask=None, n_iter=200, block_size=8, seed=None)

Costes' randomization significance test for Pearson's PCC.

Scrambles channel b in blocks n_iter times - destroying spatial co-occurrence while preserving each channel's intensity histogram and local texture - and recomputes the PCC each time to build a null distribution. The observed PCC is then placed against that null (Costes et al. 2004). A high observed PCC that sits far above the null (small p-value) is evidence of genuine colocalisation rather than chance overlap.

Works for 2D or 3D images; the arrays are cropped to a whole number of blocks in each dimension before scrambling.

PARAMETER DESCRIPTION
a

Same-shape 2D or 3D intensity arrays.

TYPE: array_like

b

Same-shape 2D or 3D intensity arrays.

TYPE: array_like

mask

Region of interest; cropped alongside a/b.

TYPE: array_like of bool DEFAULT: None

n_iter

Number of scrambles forming the null distribution.

TYPE: int DEFAULT: 200

block_size

Side length (px) of the scrambled blocks. Should approximate the point-spread-function width of the acquisition.

TYPE: int DEFAULT: 8

seed

Seed for the random generator, for reproducibility.

TYPE: int DEFAULT: None

RETURNS DESCRIPTION
dict

{'observed', 'null', 'p_value', 'z_score'}: the observed PCC over the cropped region, the array of n_iter null PCCs, the right-tailed p-value (#{null >= observed} + 1) / (n_iter + 1), and the z-score of the observed value against the null.

RAISES DESCRIPTION
ValueError

On shape mismatch, block_size < 1 or n_iter < 1, or a block_size larger than the image in any dimension.

van_steensel_ccf

van_steensel_ccf(a, b, mask=None, max_shift=20, axis=-1)

Van Steensel's cross-correlation function (CCF).

Shifts b relative to a by every integer offset in [-max_shift, +max_shift] along axis and computes Pearson's coefficient at each shift (Van Steensel et al. 1996). Genuinely colocalised channels give a CCF that peaks at shift 0; mutually excluded channels give a trough at 0 with side peaks.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays.

TYPE: array_like

b

Same-shape intensity arrays.

TYPE: array_like

mask

Region of interest passed through to pearson.

TYPE: array_like of bool DEFAULT: None

max_shift

Largest pixel shift to evaluate in each direction.

TYPE: int DEFAULT: 20

axis

Axis along which b is shifted (wraps, numpy.roll).

TYPE: int DEFAULT: -1

RETURNS DESCRIPTION
shifts

Integer offsets -max_shift … +max_shift.

TYPE: ndarray

ccf

Pearson coefficient at each shift; nan where the shifted pair is degenerate.

TYPE: ndarray

RAISES DESCRIPTION
ValueError

If a and b differ in shape or max_shift < 1.

li_ica

li_ica(a, b, mask=None)

Li's Intensity Correlation Analysis (ICA) payload.

Returns the per-pixel covariance products P_i = (a_i - mean a)(b_i - mean b) together with the paired intensities, so the widget can draw the two ICA scatter panels (intensity vs P) for channels A and B. The scalar ICQ - the fraction of positive P re-centred to [-0.5, 0.5] - is included for the summary line.

PARAMETER DESCRIPTION
a

Same-shape intensity arrays.

TYPE: array_like

b

Same-shape intensity arrays.

TYPE: array_like

mask

Region of interest.

TYPE: array_like of bool DEFAULT: None

RETURNS DESCRIPTION
dict

{'a', 'b', 'products', 'icq'}: the masked, flattened channel-A and channel-B intensities, their covariance products, and the ICQ scalar.

RAISES DESCRIPTION
ValueError

If a and b differ in shape, or the region has fewer than two pixels.

Object-based - napari_colocalization._objects

Object-level colocalization: from two labelled images, report centre-particle coincidence and object overlap per object, plus centroids and nearest-neighbour links for viewer overlays. Objects can be supplied directly or obtained with label_objects (threshold + connected components).

Pure-compute object-based colocalization.

Where _metrics works on pixel intensities, this works on segmented objects: two labelled images (objects in channel A, objects in channel B) are compared by

  • centre-particle coincidence - does an object's centroid fall inside an object of the other channel?
  • object overlap - do an object's pixels touch any object of the other channel?

It also exposes object centroids and nearest-neighbour links so the widget can draw Points / Vectors overlays. As elsewhere there are no napari/qtpy imports here, so everything operates on ndarrays and is testable headlessly. Objects can be supplied directly (a Labels layer) or obtained with label_objects (threshold + connected components).

label_objects

label_objects(image, threshold_method='otsu', mask=None, min_size=0)

Threshold an intensity image and label its connected components.

PARAMETER DESCRIPTION
image

Intensity image (2D or 3D).

TYPE: array_like

threshold_method

Auto-threshold name from the skimage.filters.threshold_* family ('otsu', 'li', 'triangle', 'yen', 'mean', 'isodata').

TYPE: str DEFAULT: 'otsu'

mask

Restrict object detection to this region.

TYPE: array_like of bool DEFAULT: None

min_size

Drop connected components smaller than this many pixels.

TYPE: int DEFAULT: 0

RETURNS DESCRIPTION
numpy.ndarray of int

Integer label image (0 = background, 1..N = objects). All zeros when the channel has no defined threshold (constant).

object_table

object_table(labels_a, labels_b, name_a='A', name_b='B')

Object-based colocalization between two labelled images.

Reports, for every object in each channel, whether its centroid is coincident with an object of the other channel and whether it overlaps one.

PARAMETER DESCRIPTION
labels_a

Same-shape integer label images (0 = background).

TYPE: array_like of int

labels_b

Same-shape integer label images (0 = background).

TYPE: array_like of int

name_a

Channel display names written into the 'channel' column.

TYPE: str DEFAULT: 'A'

name_b

Channel display names written into the 'channel' column.

TYPE: str DEFAULT: 'A'

RETURNS DESCRIPTION
rows

One row per object, with the keys in OBJECT_COLUMNS.

TYPE: list of dict

summary

Object counts and coincident/overlap counts and fractions per channel.

TYPE: dict

RAISES DESCRIPTION
ValueError

If the two label images differ in shape.

object_centroids

object_centroids(labels)

(N, ndim) array of object centroids, in axis order.

nearest_neighbour_vectors

nearest_neighbour_vectors(centroids_a, centroids_b)

Vectors from each A centroid to its nearest B centroid.

Returned as napari Vectors data (N, 2, ndim) - [start, direction] pairs. Empty when either set has no objects.

Sample data - napari_colocalization._sample_data

make_sample_data_cbs006rbm downloads the CBS006RBM benchmark image from the Colocalization Benchmark Source on first use and caches it under ~/.cache/napari-colocalization/.

Synthetic two-channel sample data for colocalization.

Synthetic samples (2D, 3D): gaussian blobs with channel B copying 60 % of channel A's blobs plus independent blobs and noise, giving PCC ~ 0.7 and Manders M1/M2 ~ 0.6.

CBS006RBM: red and blue channels with ~50 % colocalization, from the Colocalization Benchmark Source. The TIFF is downloaded once and cached in ~/.cache/napari-colocalization/.

colocsample1bRGB: a confocal Z-stack (33 x 152 x 172) with red and green dyes that strongly colocalise. Downloaded once from the Fiji sample server and cached under ~/.cache/napari-colocalization/; this is the image used by the ROI colocalization tutorial.

make_sample_data

make_sample_data()

2D sample: 256x256 channels of gaussian blobs.

make_sample_data_3d

make_sample_data_3d()

3D sample: 32x128x128 (Z, Y, X) volumes of gaussian blobs.

make_sample_data_cbs006rbm

make_sample_data_cbs006rbm()

2D sample from the Colocalization Benchmark Source (CBS006RBM).

Red and blue channels with ~50 % colocalization. Downloaded once and cached under ~/.cache/napari-colocalization/.

Source: https://colocalization-benchmark.com/

make_sample_data_coloc

make_sample_data_coloc()

2D-stack sample: red and green confocal dyes that colocalise.

The colocsample1bRGB_BG.tif confocal Z-stack (33 x 152 x 172), downloaded once from the Fiji sample server and cached locally, split into its red and green channels. The two dyes strongly colocalise (whole-stack PCC ~ 0.75).

Putting it together: scripted analysis

import numpy as np
import pandas as pd
from napari_colocalization._analysis import analyse_pairwise, COLUMNS

a = np.load('channel_a.npy')
b = np.load('channel_b.npy')
mask = np.load('cell_labels.npy')   # 0 = bg, 1..N = cells

rows = analyse_pairwise(
    a, b,
    label_mask=mask,
    metrics=('pcc', 'srcc', 'mcc'),
    threshold_method='costes',
    channel_a='dna', channel_b='tubulin',
)

df = pd.DataFrame(rows, columns=COLUMNS)
df.to_csv('colocalization_per_cell.csv', index=False)
print(df.describe())

Stability

  • The function signatures, return shapes and COLUMNS tuple above are intended to be stable across point releases.
  • Internal helpers prefixed with _ (private functions inside each module) may change without notice.
  • ColocalizationWidget (_widget.py) is the GUI surface and not part of the scripting API; for scripts, drive analyse_* directly.