Skip to content

extract_chromatin_clumps

Extract chromatin clumps from a given image and label-map.

Note

Applies a normalization to the image before extracting chromatin clumps.

Parameters:

Name Type Description Default
img ndarray

Input H&E image from which to extract chromatin clumps. Shape (H, W, 3).

required
label ndarray

Nuclei label map indicating the nuclei of interest. Shape (H, W).

required
mask ndarray

Binary mask to restrict the region of interest. Shape (H, W). For example, it can be used to mask out tissues that are not of interest.

None
mean float

Mean intensity for normalization.

0.0
std float

Standard deviation for normalization.

1.0
device str

Device to use for computation. Options are 'cpu' or 'cuda'. If set to 'cuda', CuPy and cucim will be used for GPU acceleration.

'cpu'

Raises:

Type Description
ValueError

If the shape of img and label do not match.

Returns:

Type Description
ndarray

np.ndarray: Binary mask of the extracted chromatin clumps. Shape (H, W).

Examples:

>>> from histolytics.data import hgsc_cancer_he, hgsc_cancer_nuclei
>>> from histolytics.utils.raster import gdf2inst
>>> from histolytics.nuc_feats.chromatin import extract_chromatin_clumps
>>> import matplotlib.pyplot as plt
>>>
>>> # Load example data
>>> he_image = hgsc_cancer_he()
>>> nuclei = hgsc_cancer_nuclei()
>>>
>>> # Filter for a specific cell type if needed
>>> neoplastic_nuclei = nuclei[nuclei["class_name"] == "neoplastic"]
>>>
>>> # Convert nuclei GeoDataFrame to instance segmentation mask
>>> inst_mask = gdf2inst(neoplastic_nuclei, width=he_image.shape[1], height=he_image.shape[0])
>>> # Extract chromatin clumps
>>> chrom_mask = extract_chromatin_clumps(he_image, inst_mask)
>>> fig,ax = plt.subplots(1, 2, figsize=(8, 4))
>>> ax[0].imshow(chrom_mask)
>>> ax[0].set_axis_off()
>>> ax[1].imshow(he_image)
>>> ax[1].set_axis_off()
>>> fig.tight_layout()

out

Source code in src/histolytics/nuc_feats/chromatin.py
def extract_chromatin_clumps(
    img: np.ndarray,
    label: np.ndarray,
    mask: np.ndarray = None,
    mean: float = 0.0,
    std: float = 1.0,
    device: str = "cpu",
) -> np.ndarray:
    """Extract chromatin clumps from a given image and label-map.

    Note:
        Applies a normalization to the image before extracting chromatin clumps.

    Parameters:
        img (np.ndarray):
            Input H&E image from which to extract chromatin clumps. Shape (H, W, 3).
        label (np.ndarray):
            Nuclei label map indicating the nuclei of interest. Shape (H, W).
        mask (np.ndarray):
            Binary mask to restrict the region of interest. Shape (H, W). For example,
            it can be used to mask out tissues that are not of interest.
        mean (float):
            Mean intensity for normalization.
        std (float):
            Standard deviation for normalization.
        device (str):
            Device to use for computation. Options are 'cpu' or 'cuda'. If set to 'cuda',
            CuPy and cucim will be used for GPU acceleration.

    Raises:
        ValueError: If the shape of `img` and `label` do not match.

    Returns:
        np.ndarray: Binary mask of the extracted chromatin clumps. Shape (H, W).

    Examples:
        >>> from histolytics.data import hgsc_cancer_he, hgsc_cancer_nuclei
        >>> from histolytics.utils.raster import gdf2inst
        >>> from histolytics.nuc_feats.chromatin import extract_chromatin_clumps
        >>> import matplotlib.pyplot as plt
        >>>
        >>> # Load example data
        >>> he_image = hgsc_cancer_he()
        >>> nuclei = hgsc_cancer_nuclei()
        >>>
        >>> # Filter for a specific cell type if needed
        >>> neoplastic_nuclei = nuclei[nuclei["class_name"] == "neoplastic"]
        >>>
        >>> # Convert nuclei GeoDataFrame to instance segmentation mask
        >>> inst_mask = gdf2inst(neoplastic_nuclei, width=he_image.shape[1], height=he_image.shape[0])
        >>> # Extract chromatin clumps
        >>> chrom_mask = extract_chromatin_clumps(he_image, inst_mask)
        >>> fig,ax = plt.subplots(1, 2, figsize=(8, 4))
        >>> ax[0].imshow(chrom_mask)
        >>> ax[0].set_axis_off()
        >>> ax[1].imshow(he_image)
        >>> ax[1].set_axis_off()
        >>> fig.tight_layout()
    ![out](../../img/chrom_clump_noerode.png)
    """
    if img.shape[:2] != label.shape:
        raise ValueError(
            f"Shape mismatch: img has shape {img.shape}, but label has shape {label.shape}."
        )

    if mask is not None and mask.shape != label.shape:
        raise ValueError(
            f"Shape mismatch: mask has shape {mask.shape}, but label has shape {label.shape}."
        )

    if device == "cuda" and not _has_cp:
        raise RuntimeError(
            "CuPy and cucim are required for GPU acceleration (device='cuda'). "
            "Please install them with:\n"
            "  pip install cupy-cuda12x cucim-cu12\n"
            "or set device='cpu'."
        )

    # return zeros if label empty
    if np.max(label) == 0:
        return np.zeros_like(label)

    if _has_cp and device == "cuda":
        return _extract_chrom_cp(img, label, mask, mean, std)
    else:
        return _extract_chrom_np(img, label, mask, mean, std)