Skip to main content

PALMS

Provenance-Aware Linking of Multimodal Spatial-omics

CI License: MIT Python

A napari-based viewer that brings spatial transcriptomics, histology and genomic overlays into one coordinate space — and records every action you take as replayable code. It reads 10x Genomics Xenium 3.x output, and is an open alternative to the commercial Xenium Explorer, which does not ship a Linux build. Runs on Linux, macOS and WSL2. Visualises high-resolution spatial gene expression at cell-level resolution with:

  • Cell visualisation — colour by gene expression, cluster, or metadata; load per-gene transcript point clouds and density heatmaps; linked UMAP window
  • Clustering & DEG — Leiden clustering, rank-genes, dotplots, import/export of cluster assignments; ROI-based differential expression
  • Spatial analysis — neighbourhood enrichment, co-occurrence, ligand-receptor (via squidpy/omnipath), spatial domain inference (Novae)
  • Image registration — landmark-based affine registration for H&E and ARMS fluorescence images; external OME-TIFF/SVS loader
  • Annotation tools — draw/label/export annotation shapes (GeoJSON); annotate cells by neighbourhood composition or distance to a reference population
  • Session persistence — all analyses auto-saved to a zarr cache and restored on relaunch; reproducible analysis exported as analysis.py and analysis_notebook.ipynb, accumulated across sessions

Install

The viewer pulls in a heavy scientific stack (napari, scanpy, squidpy, spatialdata, zarr, dask, Qt). The recommended way to install is via conda:

git clone https://github.com/sraorao/palms.git
cd palms

./scripts/install.sh
conda activate palms

The env file installs the core stack via conda-forge and palms itself in editable mode, so source edits in this checkout are picked up immediately. It also installs the CNV inference stack (infercnvpy and insitucnv), so the CNV tab's inferCNV backend works out of the box — no extra step needed.

install.sh is just conda env create -f environment.yml plus one OS-dependent step: on Linux and WSL it also applies environment-linux.yml, which adds libglx-devel. That package fixes a Qt6 startup abort on remote X displays but is linux-only, so it cannot live in environment.yml — with it there, the file does not solve on macOS at all. If you prefer to run conda yourself:

conda env create -f environment.yml                              # all platforms
conda env update -n palms -f environment-linux.yml       # Linux/WSL only

Skipping the second line on Linux is not silent: the viewer checks for it at startup and tells you what to run.

Optional extras

Several features depend on heavier or more niche packages that aren't installed by default. Add them on top of the core install, after conda activate palms:

pip install -e ".[celltypist]"   # CellTypist label transfer (Rank Genes tab)
pip install -e ".[r]"            # rpy2-based reference fetcher (needs system R)
pip install -e ".[gpu]"          # torch / torch-geometric / xgboost
pip install -e ".[references]"   # rasterio + readfcs
pip install -e ".[novae]"        # Novae spatial-domain inference (Domains tab)
pip install -e ".[cnv]"          # InSituCNV/infercnvpy — already in environment.yml
pip install -e ".[full]"         # all of the above

Each extra is independent — install only the ones you need. A tab whose optional dependency isn't installed still appears in the UI; it just reports a clear "not installed" error (with the pip install command to run) the first time you try to use it, instead of failing at startup.

The cnv extra is the exception: it is already covered by environment.yml, so you only need it if you installed with plain pip instead of conda. It pulls insitucnv-copykat — the insituCNV-copykat fork, published under that name because insitucnv on PyPI is upstream's. It imports as insitucnv either way, so don't install both. The fork exists because upstream's release pins anndata<0.12 and pandas<3, which cannot resolve against this app.

CopyKAT backend (optional second environment)

The CNV tab's inferCNV backend runs in the main environment. Its CopyKAT backend does not: CopyKAT needs rpy2 with R 4.3, a stack that only builds on python 3.11 and so cannot coexist with the main env's python 3.12. It therefore lives in a second environment:

conda env create -f environment-copykat.yml   # creates 'palms_copykat'

Linux only. This env is not solvable on Apple Silicon: r-dlm (a CopyKAT dependency) comes from the Anaconda r channel, which publishes no osx-arm64 builds. inferCNV runs in the main env and is unaffected on every platform.

The viewer finds that environment by name and launches CopyKAT there as a detached background job, which survives the GUI closing. The copykat R package itself is GitHub-only and installs automatically on first run. To point the viewer at a differently-named environment, set PALMS_COPYKAT_ENV (env name) or PALMS_COPYKAT_PYTHON (full path to its python).

Skip this entirely if you only need inferCNV.

Reinstalling

To wipe the environment and start fresh (e.g. after a dependency conflict or a major update), remove the old environment, re-clone the repo, and reinstall:

conda env remove -n palms

git clone https://github.com/sraorao/palms.git
cd palms
./scripts/install.sh
conda activate palms

Usage

# Launch the viewer (file dialog opens if no path given)
palms [/path/to/xenium/output]

# One-time per-gene transcript preprocessing (~30–60 min, ~1 GB output)
# Produces transcript_cache/ next to the dataset, used for fast gene loading.
palms-preprocess /path/to/xenium/output

# Build the SpatialData zarr cache without starting the GUI (tens of minutes).
# The viewer does this on first launch anyway; this is how to get it out of the
# way over ssh or overnight. `--check` reports on an existing cache instead.
palms-build-cache /path/to/xenium/output

# Skip the SpatialData zarr cache (force reload from raw output)
palms /path/to/xenium/output --no-cache

Console scripts shipped:

Command Purpose
palms Launch the GUI
palms-preprocess Build the per-gene transcript feather cache (run once)
palms-build-cache Build/inspect the SpatialData zarr cache without the GUI
palms-fetch-references Download public scRNA-seq references for label transfer
palms-build-custom-segmentation Build custom segmentation assets from Seurat extract output

You can also invoke the package directly: python -m palms ....

Repo layout

src/palms/          # the installable package
├── app.py                  # main GUI entry point (~1800 lines)
├── loader.py               # SpatialData loader with zarr cache
├── preprocess.py           # transcript feather cache builder
├── tabs/                   # 26 control-panel tab modules in 5 groups
│   │                       #   Cells: Clustering, Coloring, Transcripts, UMAP
│   │                       #   Genes: Rank Genes, Markers, Correlation, CNV
│   │                       #   Spatial: ROI DEG, Lig-Rec, Nhood Enrich,
│   │                       #            Co-occur, Domains, Annot Nhood, Annot Dist
│   │                       #   Images: H&E, ARMS, Ext Images, Patches
│   │                       #   Tools: Annotations, Segmentation, Crop Dataset,
│   │                       #          Notebook, Dataset, Cache, Templates
│   └── _helpers.py         # shared tab utilities (StatusProxy, make_tab, …)
└── utils/
    ├── viewer_context.py   # ViewerContext dataclass — shared state for all tabs
    ├── coloring.py         # CellColorManager with DirectLabelColormap
    ├── gene_analysis.py    # rank genes, normalization, Leiden clustering
    ├── spatial_analysis.py # squidpy spatial analysis wrappers
    ├── registration.py     # landmark-based affine registration
    ├── transcript_index.py # per-gene feather loader
    ├── session.py          # zarr-based session persistence
    ├── adata_persistence.py# AnnData / SpatialData result persistence
    ├── umap_widget.py      # linked UMAP scatter window
    └── …                   # annotation utils, notebook engine, patch I/O, …
scripts/
├── extract_seurat_segmentation.R   # stage-1 R script for custom segmentation
├── capture_screenshots.py          # automated wiki screenshot capture
└── push_to_wiki.sh                 # sync docs/ to GitHub Wiki
reference_datasets/                 # fetched scRNA-seq references + metadata

Documentation

Full documentation with screenshots is available on the GitHub Wiki.

  • CLAUDE.md — architecture overview and developer notes
  • CHANGELOG.md — release history

Citing PALMS

If PALMS contributes to work you publish, please cite it. CITATION.cff in the repo root holds the machine-readable metadata; GitHub's "Cite this repository" button reads it directly. A Zenodo DOI for v1.0.0 is being minted and will be added to that file.

License

MIT

Download files

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

Source Distribution

palms-1.0.0.tar.gz (527.9 kB view details)

Uploaded Source

Built Distribution

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

palms-1.0.0-py3-none-any.whl (486.5 kB view details)

Uploaded Python 3

File details

Details for the file palms-1.0.0.tar.gz.

File metadata

  • Download URL: palms-1.0.0.tar.gz
  • Upload date:
  • Size: 527.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for palms-1.0.0.tar.gz
Algorithm Hash digest
SHA256 7aed7d09cd5aac031c58de38d5dfac3c55a522fa3b608c4bd6c3950331783515
MD5 f96968b7e9808af20796e47f380486b2
BLAKE2b-256 168afcaa5e8bc391ae72cc26e20a3f3fdda33cb274623cd874249212cc22477c

See more details on using hashes here.

Provenance

The following attestation bundles were made for palms-1.0.0.tar.gz:

Publisher: release.yml on sraorao/palms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file palms-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: palms-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 486.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for palms-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bc18be097ccc8518d7bd16b8be41fe4c025266f860eddbca31bcaa15c7f0163a
MD5 b0f16034ba3c980899ec00faa5d14da6
BLAKE2b-256 17c6ef9665bb23dac0552f2562f6f29cd49ea9e4ae5fdb6cc9b5805d95abe1bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for palms-1.0.0-py3-none-any.whl:

Publisher: release.yml on sraorao/palms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.1

2 files

This release

1.0.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page