API reference

Compute

spatial_smooth.smooth(adata, genes, name='signature', *, steps='spatial', layer=None, score='mean_z', subset_key=None, include=None, exclude=None, store_genes=False, auto_embed=True, progress=False, copy=False)[source]

Smooth a gene signature through a pipeline of steps and score it per cell.

Warning

The smoothed score is for visualization only. It is spatially autocorrelated by construction, so any statistic computed on it (differential expression, clustering, correlation, a p-value of any kind) will be badly over-confident. Plot obs[name]; analyse obs[f"{name}_raw"].

The one-liner smooths over physical coordinates with a Gaussian kNN kernel:

import spatial_smooth as ss
ss.smooth(adata, ["Prox1", "Neurod6"], "hippocampus")
ss.pl.signature(adata, "hippocampus")

Choose what to smooth over with steps: "spatial" (default), "dm" (the expression manifold, via kompot.smooth_expression), or "dm+spatial" to compose both – the spatial step then consumes the manifold-denoised expression. Pass Step objects instead of a shorthand for full control.

Parameters:
  • adata – Normalised, log-transformed expression with the required obsm bases.

  • genes (Sequence[str]) – Signature genes. Duplicates are dropped, order preserved. One gene is fine.

  • name (str) – Base name for the outputs (see the module docstring’s storage contract).

  • steps (str | Step | Sequence[str | Step] | None) – A shorthand ("spatial", "dm", "dm+spatial", "spatial+dm", "spatial-kde", "spatial-gp", "none"), a single Step, or a sequence of either. Applied left to right; each step consumes the previous step’s output.

  • layer (str | None) – Expression layer to read (None -> adata.X). Should be log-normalised.

  • score (str) – Multi-gene combiner: "mean_z" (default) or "mean".

  • subset_key (str | None) – Optional cell filter applied before smoothing (see select_cells()). Filtered-out cells neither train nor receive the field. When a filter removes cells the returned object is a new, smaller AnnData – use the return value.

  • include (Iterable | None) – Optional cell filter applied before smoothing (see select_cells()). Filtered-out cells neither train nor receive the field. When a filter removes cells the returned object is a new, smaller AnnData – use the return value.

  • exclude (Iterable | None) – Optional cell filter applied before smoothing (see select_cells()). Filtered-out cells neither train nor receive the field. When a filter removes cells the returned object is a new, smaller AnnData – use the return value.

  • store_genes (bool) – Also write the smoothed (n_obs, n_genes) expression matrix to adata.obsm[f"{name}_smoothed"].

  • auto_embed (bool) – Compute a Palantir diffusion map when a step needs obsm["DM_EigenVectors"] and it is absent. Set False to fail loudly instead.

  • progress (bool) – Show the GP backend’s progress bar.

  • copy (bool) – Work on a copy and leave the input untouched.

Returns:

AnnData – The object carrying the result. Identical to the input when copy=False and no cell filter was applied.

Raises:
  • KeyError – A gene, layer, or obsm basis is missing (the message names it).

  • ImportError – An optional backend a step needs is not installed (the message gives the pip line).

See also

spatial_smooth.plot.signature

render a stored result without recomputing it.

provenance

read back exactly what was run.

spatial_smooth.compute_diffusion_map(adata, *, obsm_key='DM_EigenVectors', n_components=10, knn=30, n_pca_components=50, use_hvg=False, random_state=0, recompute=False)[source]

Compute a Palantir diffusion map and store it in adata.obsm[obsm_key].

A thin wrapper over palantir.utils.run_pca + palantir.utils.run_diffusion_maps. The diffusion map is the cell-state embedding a KompotGP step smooths over by default: nearby cells are transcriptionally similar, so smoothing there denoises along biological structure rather than physical position.

Idempotent – returns immediately if obsm_key already exists, unless recompute.

Parameters:
  • adata – Normalised, log-transformed expression.

  • obsm_key (str) – Destination key. The default matches kompot’s expectation.

  • n_components (int) – Forwarded to Palantir.

  • knn (int) – Forwarded to Palantir.

  • n_pca_components (int) – Forwarded to Palantir.

  • use_hvg (bool) – Forwarded to Palantir.

  • random_state (int) – Forwarded to Palantir.

  • recompute (bool) – Recompute even when obsm_key is present.

Returns:

AnnData – The same object, for chaining.

spatial_smooth.select_cells(adata, obs_key, *, include=None, exclude=None)[source]

Boolean mask over adata.obs selecting the cells to keep.

include keeps only the listed values; exclude drops the listed values; together they apply in that order. Values are compared as strings, so numeric and categorical columns both work.

Parameters:

Steps

Smoothing steps – the composable units of a smoothing pipeline.

A step smooths an (n_obs, n_genes) expression matrix over one embedding stored in adata.obsm. A pipeline is an ordered list of steps: each consumes the previous step’s output, so [KompotGP(), KnnGaussian()] first denoises along the expression manifold and then smooths the already-denoised values over physical space.

Three steps ship with the package:

step

default basis

engine

KnnGaussian

spatial

Gaussian kernel over k nearest neighbours

Kde

spatial

FFT Nadaraya-Watson on a fine grid (KDEpy)

KompotGP

DM_EigenVectors

Gaussian-process regression (kompot/mellon)

Every step is a frozen dataclass: it is a specification, not a fitted object. It carries no data, is trivially serialisable into adata.uns (Step.to_dict()), and can be reused across datasets.

String shorthands

resolve_steps() turns a shorthand into a pipeline, so the common cases need no imports:

shorthand

pipeline

meaning

"spatial"

[KnnGaussian()]

spatial smoothing only

"dm"

[KompotGP()]

cell-state smoothing only

"dm+spatial"

[KompotGP(), KnnGaussian()]

both, cell-state first

"spatial+dm"

[KnnGaussian(), KompotGP()]

both, spatial first

"spatial-kde"

[Kde()]

spatial, KDE engine

"spatial-gp"

[KompotGP(basis="spatial", ls_factor=0.3)]

spatial, GP engine

"none"

[]

no smoothing (raw only)

class spatial_smooth.steps.KnnGaussian(basis='spatial', k=400, sigma=None, sigma_factor=6.0, workers=-1)[source]

Bases: Step

Gaussian kernel over the k nearest neighbours – the fast default.

A row-stochastic linear smoother (see spatial_smooth.smoothers): each cell’s value becomes the Gaussian-weighted mean of its k nearest neighbours in basis. On a full imaging-based slide (~1.6e5 cells) this runs in a second or two, against several minutes for the Gaussian process at comparable output quality – so it is the default for smoothing over physical tissue coordinates.

Truncation, and what provenance reports

Restricting the kernel to k neighbours truncates it. Whichever binds first – sigma or the radius of the k-th neighbour – sets the bandwidth the data actually sees, and because that radius follows a neighbour count it shrinks where cells are dense and grows where they are sparse. The smoother is therefore truncated-Gaussian and implicitly density-adaptive, not strictly fixed-bandwidth.

spatial_smooth.provenance() records this rather than hiding it. Alongside sigma_nominal (the Gaussian’s sigma before truncation – a bandwidth no cell experiences; also written as sigma_used for backwards compatibility) it stores kernel_mass_retained (the mean fraction of the untruncated Gaussian inside each cell’s k-neighbour radius), sigma_effective (the bandwidth the kernel behaves like, from its weighted second moment) and that quantity’s 1st/99th percentiles across cells. Quote ``sigma_effective`` in a methods section, never ``sigma_nominal``/``sigma_used``. When the retained mass falls below MIN_KERNEL_MASS a UserWarning names both numbers and tells you to raise k.

The default k=400 keeps ~96% of the mass at sigma_factor=6.0 on 2-D tissue, where roughly 210 cells lie within 2 * sigma; sigma_effective then tracks sigma_used closely. (k=100 retains only ~58%, pulling the effective bandwidth to ~0.6 x sigma with a ~2.8x spread across cells.)

param basis:

adata.obsm key to smooth over. Defaults to "spatial".

type basis:

str

param k:

Neighbours per cell, self included. Not a free performance knob – see above.

type k:

int

param sigma:

Bandwidth in coordinate units. None (default) infers it scale-invariantly as sigma_factor x the median nearest-neighbour distance.

type sigma:

float | None

param sigma_factor:

Multiplier on the median nearest-neighbour distance when sigma is inferred.

type sigma_factor:

float

param workers:

Threads for the kd-tree query (-1 = all cores).

type workers:

int

basis: str = 'spatial'

Key into adata.obsm giving the coordinates this step smooths over.

k: int = 400
sigma: float | None = None
sigma_factor: float = 6.0
workers: int = -1
kind: str = 'knn_gaussian'

Human-readable name recorded in provenance.

Parameters:
class spatial_smooth.steps.Kde(basis='spatial', grid_points=1024, bw=None, bw_factor=6.0, min_density_pct=1.0)[source]

Bases: Step

Fine-grid FFT Nadaraya-Watson smoothing (KDEpy). Two-dimensional bases only.

Comparable in speed to KnnGaussian and also row-stochastic, but resolution-bound: detail finer than one grid cell is lost. Useful when you want a rendered field rather than a neighbour average, or when point density varies enough that a fixed k misbehaves.

Parameters:
  • basis (str) – adata.obsm key – must be 2-D.

  • grid_points (int) – Grid resolution per axis.

  • bw (float | None) – Bandwidth in coordinate units. None -> bw_factor x median NN distance.

  • bw_factor (float) – Multiplier on the median nearest-neighbour distance when bw is inferred.

  • min_density_pct (float) – Percentile of the uniform-KDE density below which a grid cell counts as empty background and contributes no signal.

basis: str = 'spatial'

Key into adata.obsm giving the coordinates this step smooths over.

grid_points: int = 1024
bw: float | None = None
bw_factor: float = 6.0
min_density_pct: float = 1.0
kind: str = 'kde'

Human-readable name recorded in provenance.

class spatial_smooth.steps.KompotGP(basis='DM_EigenVectors', sigma=1.0, ls=None, ls_factor=10.0, n_landmarks=5000, groupby=None, condition=None, random_state=0)[source]

Bases: Step

Gaussian-process regression per gene via kompot.smooth_expression.

Fits a GP of each gene over basis and evaluates it on every cell, so neighbouring cells borrow statistical strength. Slower than KnnGaussian – the GP solve dominates – but it is the only step that models a length scale explicitly, returns a posterior, and supports fit on one condition, evaluate everywhere via groupby/condition.

Defaults target the cell-state use: basis="DM_EigenVectors" (a diffusion map of the expression manifold) with kompot’s native ls_factor=10.

Length scale is scale-invariant

With ls=None (the default) kompot/mellon infer the length scale empirically from the data’s nearest-neighbour distances – ls_base = geometric_mean(nn_distances) * e**3 (mellon.parameters.compute_ls) – and multiply it by ls_factor. Because ls_base is proportional to the point spacing, the same ls_factor yields the same smoothing regardless of the coordinates’ absolute scale (microns vs millimetres).

Over a diffusion map the native ls_factor=10 is right. Over physical coordinates it is roughly 200x the cell spacing and washes the field into a single global gradient; use ls_factor=0.3 there (~6 cell spacings, matching KnnGaussian’s default footprint). The "spatial-gp" shorthand does exactly that.

param basis:

adata.obsm key to smooth over. Defaults to "DM_EigenVectors".

type basis:

str

param sigma:

GP noise level.

type sigma:

float

param ls:

Explicit length scale in coordinate units; bypasses the empirical path entirely.

type ls:

float | None

param ls_factor:

Multiplier on the empirically inferred length scale (used when ls is None).

type ls_factor:

float

param n_landmarks:

Inducing points for mellon’s Nystrom approximation. A small effective length scale needs enough landmarks that the landmark spacing stays below it.

type n_landmarks:

int

param groupby:

When both are given the GP is fitted only on cells with adata.obs[groupby] == condition and evaluated on all cells.

param condition:

When both are given the GP is fitted only on cells with adata.obs[groupby] == condition and evaluated on all cells.

param random_state:

Seed for landmark selection.

type random_state:

int

basis: str = 'DM_EigenVectors'

Key into adata.obsm giving the coordinates this step smooths over.

sigma: float = 1.0
ls: float | None = None
ls_factor: float = 10.0
n_landmarks: int = 5000
groupby: str | None = None
condition: str | None = None
random_state: int = 0
kind: str = 'kompot_gp'

Human-readable name recorded in provenance.

Parameters:
class spatial_smooth.steps.Step(basis='spatial')[source]

Bases: object

Base class for a smoothing step. Not used directly.

Parameters:

basis (str)

basis: str = 'spatial'

Key into adata.obsm giving the coordinates this step smooths over.

kind: str = 'step'

Human-readable name recorded in provenance.

apply(matrix, adata, genes, *, progress=False)[source]

Smooth matrix ((n_obs, n_genes)) over adata.obsm[self.basis].

Returns (smoothed_matrix, resolved_params) where resolved_params records the values actually used (e.g. an inferred bandwidth) for provenance.

Parameters:
to_dict()[source]

JSON-serialisable specification of this step (for adata.uns).

Return type:

Dict[str, Any]

spatial_smooth.steps.resolve_steps(spec)[source]

Turn a shorthand, a step, or a sequence of either into a list of Step.

Examples

>>> resolve_steps("spatial")
[KnnGaussian(basis='spatial', k=400, ...)]
>>> len(resolve_steps("dm+spatial"))
2
>>> resolve_steps(None)
[]
Parameters:

spec (str | Step | Sequence[str | Step] | None)

Return type:

List[Step]

Reading results back

spatial_smooth.provenance(adata, name='signature')[source]

Read back what smooth() did, with the pipeline decoded.

The returned dict is the stored record with an extra "steps" entry: the list of step specifications, each including a "resolved" sub-dict of the values actually used (an inferred bandwidth, the kompot version, …).

Raises:

KeyError – If no result called name is stored – the message lists what is stored.

Parameters:

name (str)

Return type:

Dict[str, Any]

spatial_smooth.list_results(adata)[source]

Names of every stored smoothing result in adata.

Return type:

List[str]

Plotting

Plotting – a thin, transparent wrapper over scanpy and squidpy.

This module never computes anything. It reads the keys spatial_smooth.core.smooth() wrote into the AnnData (obs[name], obs[f"{name}_raw"], uns["spatial_smooth"][name]), works out sensible defaults from the recorded provenance, and hands everything to an existing plotting function. Write a smoothed object to .h5ad, reload it anywhere, and these calls render it – no kompot, KDEpy or palantir needed, and no smoothing repeated.

Backends and where your **kwargs go

backend

underlying call

when to use it

"squidpy"

squidpy.pl.spatial_scatter

tissue coordinates, optional image

"scanpy"

scanpy.pl.embedding

any obsm basis, imageless

"scanpy-spatial"

scanpy.pl.spatial

Visium-style uns["spatial"] image

"auto" (default)

squidpy if installed, else scanpy

Every **kwargs is forwarded verbatim to that function. color is set by this module (to the raw and smoothed obs columns); passing it raises TypeError rather than being silently ignored. Everything else – cmap, size, figsize, vmin/vmax, title, save, ax – is the backend’s own parameter, documented in the backend’s own docstring. Defaults this module supplies (a perceptually uniform colour map, percentile colour limits where the backend supports them, a grey na_color) are applied only when you have not passed that key yourself.

Two conventions this module does normalise, because leaving them to the backend produced plots that differed for the same data:

Orientation. Imaging platforms store cell centroids as image coordinates – origin top-left, y increasing downward. squidpy.pl.spatial_scatter honours that; scanpy.pl.embedding treats obsm["spatial"] as an abstract Cartesian embedding and draws y upward, mirroring the tissue vertically. Whenever the basis being drawn is "spatial", this module inverts the y-axis and sets equal aspect, so every backend renders the section as the microscope saw it.

``size`` is backend-native and is deliberately not translated. In scanpy it is the marker area in points squared; in squidpy it is a scale factor on the inferred spot size (default 1.0). A size=6 that looks right in one is nearly invisible in the other, so this module does not pretend they mean the same thing.

What it does do is pick a sane default for the scanpy backends on a spatial basis, where scanpy’s own 120000 / n_obs leaves visible gaps between cells and the field reads as speckle rather than anatomy. default_marker_size() keeps the 1 / n_obs area scaling and raises the constant, so the section renders continuous. Pass size yourself to override.

spatial_smooth.plot.signature(adata, name='signature', *, raw=True, backend='auto', basis=None, **kwargs)[source]

Plot a stored smoothing result – raw next to smoothed, by default.

Reads only what spatial_smooth.smooth() stored. Nothing is recomputed, so this works on a reloaded .h5ad in an environment without the smoothing backends installed.

Parameters:
  • adata – Object carrying a result named name.

  • name (str) – The result to plot.

  • raw (bool) – Show the unsmoothed score alongside the smoothed one (two panels).

  • backend (str) – "auto", "squidpy", "scanpy", or "scanpy-spatial". See the module docstring for what each delegates to.

  • basis (str | None) – adata.obsm key to lay the cells out on. Defaults to the last smoothing step’s basis when that is "spatial", else the first of spatial/X_umap/X_pca present.

  • **kwargs – Forwarded verbatim to the backend’s plotting function.

Returns:

Whatever the backend returns (usually None when it shows, or axes when show=False).

Raises:

KeyError – If no result named name is stored (the message says how to create it).

spatial_smooth.plot.compare(adata, names, *, raw=False, backend='auto', basis=None, **kwargs)[source]

Plot several stored results side by side – e.g. one panel per smoothing pipeline.

compare(adata, ["sig_spatial", "sig_dm", "sig_both"]) puts the three composition modes on a common canvas. With raw=True the first panel is the (shared) unsmoothed score.

Parameters:
spatial_smooth.plot.available_backends()[source]

Backends whose plotting library is importable right now.

Return type:

List[str]

Smoothing kernels

Low-level smoothing kernels.

Each function here maps (coords, values) -> smoothed values and knows nothing about AnnData. Two of them are linear and row-stochastic – they replace each point’s value by a weighted average of its neighbours’ values with weights summing to one:

Row-stochasticity is the property that makes the package’s scoring contract exact: a constant field is left unchanged, so smoothing the individual genes and then combining them into a z-scored signature score gives exactly the same answer as combining first and smoothing the score (see spatial_smooth.core.smooth()). The Gaussian-process smoother (KompotGP) is linear but not row-stochastic, so it is applied per gene.

All bandwidths default to a scale-invariant setting: a multiple of the median nearest-neighbour distance of coords. The same factor therefore produces the same amount of smoothing whether coordinates are in microns, millimetres, or arbitrary embedding units.

spatial_smooth.smoothers.knn_gaussian_operator(coords, *, k=400, sigma=None, sigma_factor=6.0, workers=-1, return_info=False)[source]

Build the sparse row-stochastic Gaussian kNN smoothing operator W.

W[i, j] = exp(-d(i, j)**2 / (2 * sigma**2)) for the k nearest neighbours j of i (self included), each row normalised to sum to one. Applying W to any field replaces every value with the Gaussian-weighted mean of its k nearest neighbours.

It costs one cKDTree query (O(n log n)) plus a sparse mat-vec (O(n * k)) per field – orders of magnitude cheaper than a Gaussian-process fit, and the recommended default for smoothing over physical tissue coordinates.

Parameters:
  • coords(n, d) array of coordinates (physical positions, or any embedding).

  • k (int) – Neighbours per point, including the point itself. Capped at n. See the truncation note below – k is not a free performance knob, it changes the estimator.

  • sigma (float | None) – Gaussian bandwidth in coordinate units. None (default) sets it scale-invariantly to sigma_factor * median_nn_distance(coords).

  • sigma_factor (float) – Multiplier on the median nearest-neighbour distance when sigma is inferred. The default 6.0 is ~6 cell spacings.

  • workers (int) – Threads for the kd-tree query (-1 uses all cores; cap via the environment on a shared machine).

  • return_info (bool) – Also return a diagnostics dict (see below).

Returns:

  • W (scipy.sparse.csr_matrix) – (n, n) row-stochastic operator.

  • sigma (float) – The nominal bandwidth: the sigma of the Gaussian before truncation.

  • info (dict, only if return_info) – kernel_mass_retained – the mean fraction of the untruncated 2-D Gaussian’s mass that falls inside each point’s k-neighbour radius. This assumes locally uniform point density, so it is an estimate of the discrete retained-weight fraction rather than an exact accounting; it is biased slightly low (conservative). sigma_effective – the mean bandwidth actually applied, recovered from the weighted second moment (sqrt(E_w[d**2] / 2)); and its 1st/99th percentiles across points.

Notes

Truncation makes the kernel density-adaptive. Neighbours beyond the k-th get zero weight even where sigma would give them a real one, so the effective bandwidth is set by whichever of sigma and the k-neighbour radius binds first. Because the radius is fixed by a neighbour count, it shrinks in dense regions and grows in sparse ones: this is a truncated-Gaussian kNN smoother, not a strictly fixed-bandwidth one.

The default k=400 with sigma_factor=6.0 retains ~96% of the kernel mass on 2-D tissue (~210 points lie within 2 * sigma at typical imaging-assay densities), so the truncation is mild and sigma and sigma_effective nearly agree. Lowering k tightens the smoother and reduces the effective bandwidth: at k=100 only ~58% of the mass survives, sigma_effective falls to ~0.6 * sigma, and it varies ~2.8x across cells with local density. Quote sigma_effective, not sigma, in a methods section – spatial_smooth.provenance() records both.

spatial_smooth.smoothers.smooth_matrix_knn_gaussian(coords, matrix, *, k=400, sigma=None, sigma_factor=6.0, workers=-1)[source]

Apply knn_gaussian_operator() to every column of matrix.

See that function’s Notes on k-truncation: the kernel is truncated-Gaussian and implicitly density-adaptive, and the returned sigma is the nominal one.

Parameters:
  • coords(n, d) coordinates.

  • matrix(n, g) field(s) to smooth – one column per gene, or a single score column.

  • k (int)

  • sigma (float | None)

  • sigma_factor (float)

  • workers (int)

Returns:

(numpy.ndarray, float) – The (n, g) smoothed matrix and the bandwidth used.

spatial_smooth.smoothers.smooth_field_knn_gaussian(coords, values, **kwargs)[source]

1-D convenience wrapper around smooth_matrix_knn_gaussian().

Returns (smoothed_values, sigma_used) where smoothed_values has shape (n,).

spatial_smooth.smoothers.smooth_matrix_kde(coords, matrix, *, grid_points=1024, bw=None, bw_factor=6.0, min_density_pct=1.0, workers=-1)[source]

Fine-grid Nadaraya-Watson smoothing via FFT-KDE (KDEpy).

Estimates the smoothed field on a regular grid_points x grid_points grid as the ratio of two FFT-accelerated kernel density estimates – one weighted by the field, one uniform – then bilinearly interpolates back to each input point. The FFT is what makes a fine grid cheap: cost is O(grid_points**2 log grid_points) regardless of how the points cluster.

The estimator is affine, so negative values (z-scored signatures) are handled exactly by shifting the field non-negative for the KDE and shifting back afterwards.

Parameters:
  • coords(n, 2) coordinates. Two-dimensional only – this is a tissue-plane smoother.

  • matrix(n, g) field(s) to smooth.

  • grid_points (int) – Grid resolution per axis.

  • bw (float | None) – Kernel bandwidth in coordinate units. None -> bw_factor * median_nn_distance.

  • bw_factor (float) – Multiplier on the median nearest-neighbour distance when bw is inferred.

  • min_density_pct (float) – Grid cells whose uniform-KDE density falls below this percentile (of the positive densities) are treated as empty background: they are excluded from the Nadaraya-Watson ratio and then backfilled with the field’s median before interpolation, which stops NaNs bleeding inward from the tissue edge. Background therefore contributes the median, not nothing – it cannot invent structure, but it is not absent either.

  • workers (int)

Returns:

(numpy.ndarray, float) – The (n, g) smoothed matrix and the bandwidth used, in the caller’s coordinate units.

Notes

The estimate is computed in units of the median nearest-neighbour distance. KDEpy solves for its kernel’s practical support numerically, and that solve is not scale-free – it raises on a bandwidth of a few hundred microns even though such a bandwidth is perfectly ordinary on a tissue section. Rescaling makes the smoother genuinely invariant to the coordinate units.

A constant column is returned unchanged. Smoothing a constant field is the identity for any row-stochastic estimator, and the Nadaraya-Watson ratio cannot express it: KDEpy normalises its weights by their sum, so an all-zero weight vector (which a constant column becomes after the affine shift) divides by zero. A gene absent from the selected cells is routine, so this is a real input, not a pathological one.

spatial_smooth.smoothers.smooth_field_kde(coords, values, **kwargs)[source]

1-D convenience wrapper around smooth_matrix_kde().

spatial_smooth.smoothers.median_nn_distance(coords, *, workers=-1)[source]

Median distance from each point to its nearest other point.

The natural length unit of a point cloud, and the basis of every scale-invariant bandwidth in this package.

Parameters:

workers (int)

Return type:

float

Environment

spatial_smooth.check_dependencies(verbose=True)[source]

Report which dependencies are importable and at which version.

Prints a table and returns {package: version or None}. Call it at the top of a script or notebook to surface gaps before the analysis starts, each with the exact pip install line that fixes it.

Parameters:

verbose (bool)

Return type:

Dict[str, str | None]