Skip to content

Difference-of-Gaussians (dog) plugin

patchworks.plugins.dog.dog_label_fn(low_sigma: float | tuple[float, ...], high_sigma: float | tuple[float, ...], threshold: float, *, use_gpu: bool = False, decon_kwargs: dict[str, Any] | None = None, voxel_size: dict[str, float] | None = None) -> Callable[[np.ndarray], np.ndarray]

Return a ready-to-use DoG labeler for tile_process.

Parameters:

Name Type Description Default
low_sigma float | tuple[float, ...]

Gaussian sigmas (pixels) for the narrow/wide blur. dog = blur(low_sigma) - blur(high_sigma).

required
high_sigma float | tuple[float, ...]

Gaussian sigmas (pixels) for the narrow/wide blur. dog = blur(low_sigma) - blur(high_sigma).

required
threshold float

Binary threshold applied to the DoG image (dog > threshold).

required
use_gpu bool

Run gaussian_filter + label on GPU via cupy/cupyx instead of scipy. Independent of decon_kwargs — pycudadecon always needs a CUDA GPU regardless of this flag (it takes/returns plain NumPy), and this flag only picks the backend for the blur/label steps that follow.

False
decon_kwargs dict[str, Any] | None

If given, each tile is first deconvolved via pycudadecon.decon(block, **decon_kwargs) before the DoG step. None (default) skips deconvolution. pycudadecon is CUDA-only, so a SLURM job running this needs a GPU allocated regardless of use_gpu above. Widen tile_process's overlap to cover the PSF support when deconvolving, so edge tiles don't get truncated context.

dxdata/dzdata/dxpsf/dzpsf are filled in from voxel_size when you leave them out, so the voxel sizes cannot drift away from the image they describe. Anything you set explicitly wins.

None
voxel_size dict[str, float] | None

Physical voxel size as {"z": .., "y": .., "x": ..}. The Snakemake workflow passes the image's own calibration automatically; from the API, :func:patchworks.plugins.ome_zarr.read_pixel_size reads it from a store.

None

Returns:

Type Description
Callable[[ndarray], ndarray]

Picklable function ready for tile_process.

Source code in src/patchworks/plugins/dog.py
def dog_label_fn(
    low_sigma: float | tuple[float, ...],
    high_sigma: float | tuple[float, ...],
    threshold: float,
    *,
    use_gpu: bool = False,
    decon_kwargs: dict[str, Any] | None = None,
    voxel_size: dict[str, float] | None = None,
) -> Callable[[np.ndarray], np.ndarray]:
    """Return a ready-to-use DoG labeler for ``tile_process``.

    Parameters
    ----------
    low_sigma, high_sigma:
        Gaussian sigmas (pixels) for the narrow/wide blur.
        ``dog = blur(low_sigma) - blur(high_sigma)``.
    threshold:
        Binary threshold applied to the DoG image (``dog > threshold``).
    use_gpu:
        Run gaussian_filter + label on GPU via cupy/cupyx instead of scipy.
        Independent of ``decon_kwargs`` — pycudadecon always needs a CUDA
        GPU regardless of this flag (it takes/returns plain NumPy), and this
        flag only picks the backend for the blur/label steps that follow.
    decon_kwargs:
        If given, each tile is first deconvolved via
        ``pycudadecon.decon(block, **decon_kwargs)`` before the DoG step.
        ``None`` (default) skips deconvolution. pycudadecon is CUDA-only, so
        a SLURM job running this needs a GPU allocated regardless of
        ``use_gpu`` above. Widen ``tile_process``'s ``overlap`` to cover the
        PSF support when deconvolving, so edge tiles don't get truncated
        context.

        ``dxdata``/``dzdata``/``dxpsf``/``dzpsf`` are filled in from
        *voxel_size* when you leave them out, so the voxel sizes cannot drift
        away from the image they describe. Anything you set explicitly wins.
    voxel_size:
        Physical voxel size as ``{"z": .., "y": .., "x": ..}``. The Snakemake
        workflow passes the image's own calibration automatically; from the
        API, :func:`patchworks.plugins.ome_zarr.read_pixel_size` reads it from
        a store.

    Returns
    -------
    Callable[[ndarray], ndarray]
        Picklable function ready for ``tile_process``.
    """
    if use_gpu:
        _require_cupy()
    if decon_kwargs is not None:
        _require_pycudadecon()
        if voxel_size:
            # Derived values fill gaps only -- an explicit dxpsf for a PSF
            # sampled differently from the data must not be overwritten.
            derived = decon_voxel_kwargs(voxel_size)
            missing = {
                k: v for k, v in derived.items() if k not in decon_kwargs
            }
            if missing:
                logger.info(
                    "decon voxel sizes taken from the image calibration: %s",
                    missing,
                )
                decon_kwargs = {**decon_kwargs, **missing}
    cfg = {
        "low_sigma": low_sigma,
        "high_sigma": high_sigma,
        "threshold": threshold,
        "use_gpu": use_gpu,
        "decon_kwargs": decon_kwargs,
    }
    return partial(_run, dog_dict=cfg)