Skip to main content

visualize histology images with umap

Project description

histomap

Napari dock widget to overlay tile polygons and table annotations from SpatialData onto an H&E image, and to interactively select cells in a 2D embedding (e.g., UMAP in AnnData.obsm) and visualize the selected regions on the H&E.

  • Overlay mode: color polygons on the H&E by an AnnData.obs column (categorical or numeric) from SpatialData.tables[<name>].
  • UMAP-lasso mode: open a 2D embedding from AnnData.obsm (e.g., X_umap), lasso points, and preview the corresponding tile polygons on the H&E; optionally save the selection back to obs.

Installation

# Recommended: use a fresh environment
conda create --name histomap python=3.11 -y
conda activate histomap

# If published on PyPI:
pip install histomap

# If installing from source in this repo:
# pip install -e .

Runtime dependencies (installed automatically if from PyPI)

  • napari, PyQt5, magicgui
  • geopandas, shapely
  • anndata, matplotlib, spatialdata
  • (Optional, for robust SVS reading) openslide-python, napari-openslide

Windows notes

  • If geopandas/shapely wheels fail, upgrade pip (pip install -U pip) and try again.
  • For OpenSlide, install the prebuilt binaries or use conda install -c conda-forge openslide openslide-python in the same environment.

Optional GPU acceleration (RAPIDS/cuML + CuPy)

The histomap.umap function auto-detects GPU and uses RAPIDS (cuML + CuPy) when available; otherwise it falls back to umap-learn on CPU. You do not need RAPIDS for CPU-only usage.

  • macOS: RAPIDS/CUDA is not supported; use CPU (umap-learn).
  • Linux with NVIDIA GPU: install RAPIDS packages into the same environment (versions must match your CUDA/driver).

Example using conda:

# Create a GPU environment (adjust Python/CUDA/RAPIDS versions to your system)
conda create --name histomap-gpu python=3.11 -y
conda activate histomap-gpu

# Install RAPIDS UMAP dependencies (channels may vary depending on versions)
conda install -c rapidsai -c conda-forge -c nvidia cuml cupy

# Then install histomap (CPU deps via pip) into the same env
pip install histomap  # or: pip install -e .

Verification:

python - <<'PY'
import cupy
print('CUDA devices:', cupy.cuda.runtime.getDeviceCount())
PY

If RAPIDS is present and a CUDA device is available, histomap.umap(...) will automatically use the GPU; otherwise it will run on CPU.


Quick start

import histomap as hm

Method 1 — Use a SpatialData object

import spatialdata as sd
import histomap as hm

sda = sd.read_zarr("/path/to/spatialdata.zarr")

# Preferred: pass the H&E path explicitly (best on Windows)
viewer = hm.histomap(
    sda,
    imagePath="/path/to/HE_image.svs",   # alias: imagePath="/path/to/HE_image.svs"
    # mpp=0.263049,                     # µm/px (optional; if tiles are in microns, scale=1/mpp is auto-applied)
)

# If you omit imagePath, histomap will try to parse a path from str(sda).
# If no path is found, you’ll see a dialog asking you to pass imagePath explicitly.

Typical workflow in the UI

  1. Click Open WSI in Viewer (if not already opened).
  2. Choose a Table (from sda.tables), Data axis (obs or obsm), and a column/key.
    • For obs: click Render Overlay to color polygons on the H&E.
    • For obsm (e.g., X_umap): click Open UMAP + Lasso, lasso points, and inspect the green Lasso preview on the H&E.
  3. Optionally enter a Layer name and obs column, then click Save selection to write labels into AnnData.obs and add a persistent overlay layer.

Method 2 — Use with lazyslide/wsidata

import lazyslide as zs
from wsidata import open_wsi
import histomap as hm

wsi = open_wsi("/path/to/HE_image.svs")

# Assuming tiling & feature extraction are already done, e.g.:
# zs.pp.tile_tissues(wsi, tile_px=256, mpp=0.5)
# zs.tl.feature_extraction(wsi, model='chief')

# Launch viewer and overlay tiles/annotations stored in wsi.tables / wsi.shapes
viewer = hm.histomap(wsi)

Parameters (entry point)

viewer = hm.histomap(
    sda_or_wsi,                        # SpatialData or compatible WSIData
    *,
    imagePath=None,                     # str | Path | None; preferred image to open (alias: imagePath)
    mpp=None,                          # float | None; µm/px. If provided and no explicit scale, applies scale=(1/mpp, 1/mpp)
    global_to_pixel_scale=None,        # (sx, sy) override for polygon transform
    global_to_pixel_translate=None,    # (tx, ty) override
    theme="dark",
    canvas_bg="white",
)

Precedence

  • If global_to_pixel_scale is provided, it overrides mpp.
  • If imagePath is provided, it overrides any path parsed from SpatialData.
  • If neither imagePath nor a parsable path exists, histomap shows a dialog explaining how to pass imagePath.

Data assumptions

  • sda.shapes["tiles"] is a GeoDataFrame with polygons; its index contains tile IDs.
  • sda.tables[<name>] is an AnnData where obs_names match the tile IDs (string-matched; dtype mismatches are handled).
  • For UMAP-lasso, AnnData.obsm[<key>] contains an (n_cells, 2+) embedding (e.g., X_umap).

Tips & alignment

  • Tiles already in pixels? Don’t pass mpp. Use Calibrate (fit tiles) if needed.
  • Tiles in microns? Pass mpp=<µm/px> and click Auto-align (use MPP) (or rely on the automatic scale if you didn’t override with global_to_pixel_scale).
  • The overlay layers inherit the image layer’s affine, so they remain aligned across pyramid levels.

Saving lasso selections (what gets written)

When you click Save selection:

  • The chosen obs column is created/normalized as plain Python strings (dtype=object) with no missing values.
  • Only selected rows receive the provided label (string). Non-selected rows remain unchanged (empty string by default).
  • A persistent overlay layer is added with the saved selection (the transient Lasso preview is removed).

Why object strings?
Writing pandas’ nullable string dtype (dtype="string") to Zarr requires opting in (anndata.settings.allow_write_nullable_strings=True). Using plain object strings avoids that requirement and is maximally portable.


Troubleshooting

❗️“boolean value of NA is ambiguous” during wsi.write() / SpatialData.write()

You likely have pd.NA or mixed types in AnnData.obs. Ensure no NA in string-like columns and that they are object strings.

❗️“allow_write_nullable_strings is False”

Either set:

import anndata as ad
ad.settings.allow_write_nullable_strings = True

or convert to object strings.

❗️Cannot overwrite/move files on Windows after closing the viewer

Clear layers before saving: viewer.layers.clear() and run garbage collection.

❗️No H&E appears and you see “H&E Image Missing”

Pass the image explicitly:

viewer = hm.histomap(sda, imagePath="/absolute/path/to/HnE.svs")

FAQ

Q: Do I need openslide?
A: Only if you’re opening .svs/WSI formats through Napari.

Q: Can I use a custom image and MPP without modifying the dock UI?
A: Yes—pass imagePath=... and mpp=... to hm.histomap(...).


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

histomap-0.1.10.tar.gz (23.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

histomap-0.1.10-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

File details

Details for the file histomap-0.1.10.tar.gz.

File metadata

  • Download URL: histomap-0.1.10.tar.gz
  • Upload date:
  • Size: 23.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for histomap-0.1.10.tar.gz
Algorithm Hash digest
SHA256 a21abaf4dab8cf8a071db24253b98bcf2e7c56f587108547e5828f5630e38152
MD5 a455a8ed90bb83bd37c203f4ddf21a00
BLAKE2b-256 97b239a7743eaaaacc3742c9f1f36033aa73a60ac5c875590e1aee3221f712c5

See more details on using hashes here.

File details

Details for the file histomap-0.1.10-py3-none-any.whl.

File metadata

  • Download URL: histomap-0.1.10-py3-none-any.whl
  • Upload date:
  • Size: 22.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.14

File hashes

Hashes for histomap-0.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 aa93cb6e0667277b083a1463962069f07920612f3a99e760f1b44799af362597
MD5 713a67b0451ae5e0758eafc6c19c4aff
BLAKE2b-256 f56915a50e88c114ab1fccd73d2ab6eb4a254ac4eb019325e31d0b1d650d2c54

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page