Skip to content

About

GPU accelerated post-processing for 2D or 3D imaging spatial transcriptomics data.

Topics

Resources

Contributing

Stars

10 stars

Watchers

1 watching

Forks

Repository files navigation

merfish3d-analysis

WARNING: under active development. Please expect breaking changes.

GPU accelerated post-processing for 2D / 3D iterative barcoded FISH data. This package is currently NVIDIA only and Linux only. Documentation, including examples, is available at https://qi2lab.github.io/merfish3d-analysis/.

Associated preprint publication

GPU-accelerated, self-optimizing processing for 3D multiplexed iterative RNA-FISH experiments.

Try it without installation

You can try out the package in the cloud on simulated data using a Google Colab notebook that demonstrates data preprocessing and decoding.

Sample data

The GPU integration test workflow uses the StatPhysBio MERFISH simulations archived on Zenodo. Download the simulation test data or follow the complete synthetic-data example for checksum verification, extraction, model setup, and test commands.

Installation

This project uses one uv environment based on CUDA 12.9 runtime/toolkit. You need a compatible NVIDIA driver installed on the machine.

Install uv if needed:

curl -LsSf https://astral.sh/uv/install.sh | sh

Clone the repository and enter it:

git clone https://github.com/QI2lab/merfish3d-analysis
cd merfish3d-analysis

Create and sync the environment:

uv sync

For development tools, include the dev group:

uv sync --group dev

For documentation tools, include the docs group:

uv sync --group docs

Run package entry points through uv run, for example:

uv run qi2lab-preprocess /path/to/experiment

Registration conventions

Local fiducial registration uses the qi2lab GPU registration path: lateral XY registration on max-Z projections, XYZ registration, and optional SOFIMA residual flow fields after affine fiducial alignment. Global registration and fused fiducial OME-Zarr creation follow the multiview-stitcher workflow, using CPU registration and CPU direct-to-Zarr fusion.

Fuse all channels

After local and global registration, fuse the first-round fiducial and codebook bits into qi2labdatastore/fused/full_dataset.ome.zarr:

uv run qi2lab-fuseall /path/to/experiment \
  --output-chunk-zyx 32,2048,2048 \
  --fusion-workers 30 \
  --compression blosc-lz4 \
  --compression-level 1

All output levels use lossless compression. The shared default for fiducial and all-channel fusion is blosc-zstd with bitshuffle at level 1. The example selects blosc-lz4 with bitshuffle for faster encoding; compression ratio and speed depend on the data. zstd is also available. Levels 1 through 9 are accepted; compression cannot be disabled. Changing compression preserves the pixel values produced by fusion.

The output is OME-Zarr v0.5, with the fiducial first and then bits in numeric codebook order. The command uses stored chromatic, local-round, stage and global transforms; SOFIMA is omitted. See the fusion workflow for resource settings and restart behavior.

View a qi2lab datastore

The standard uv sync install includes the NDV, VisPy, and PyQt dependencies for the view-only datastore GUI.

Open an experiment root:

uv run viewer /path/to/experiment

or open a datastore directly:

uv run viewer /path/to/experiment/qi2labdatastore

The viewer only reads existing datastore contents. It uses NDV for Zarr-backed image channels and VisPy for sparse transcript and cell-boundary overlays. It can inspect local native tiles, local tiles warped with selected chromatic, stage/round affine, and SOFIMA components, and global fused views. Transcript sources are mutually exclusive: datastore transcripts, Proseg transcripts, or Baysor transcripts. Cell boundaries can be shown from Cellpose, Proseg, or Baysor when those outputs are present.

The documentation includes a viewer guide with screenshots and a current API notes page covering the current RLGC, PSF, and U-FISH defaults.

Proseg segmentation optimization

Follow the installation instructions at proseg.

Example calls to proseg:

2D segmentation optimization (ignore z coordinate)

mkdir /path/to/qi2labdatastore/proseg/2D

/path/to/proseg --gene-column gene_id -x global_x -y global_y -z global_z --fov-column tile_idx --cell-id-column cell_id --cell-id-unassigned 0 --excluded-genes ^[Bb]lank.*$ --ignore-z-coord --density-bins 1 --burnin-samples 1000 --samples 2000 --voxel-size 1.0 --burnin-voxel-size 4.0 --enforce-connectivity --diffusion-probability 0.0 --output-spatialdata /path/to/data/qi2labdatastore/proseg/2D/spatialdata_2D.zarr --output-counts /path/to/data/qi2labdatastore/proseg/2D/counts_2D.mtx.gz --output-cell-polygons /path/to/data/qi2labdatastore/proseg/2D/cell_polygons_2D.geojson.gz --output-transcript-metadata /path/to/data/qi2labdatastore/proseg/2D/transcript_metadata_2D.csv.gz /path/to/data/qi2labdatastore/all_tiles_filtered_decoded_features/decoded_features.csv.gz

3D segmentation optimization. Here --voxel-layers should be roughly set to the height of the imaged volume in microns. For example, a 15 micron thick sample should have --voxel-layers 15.

mkdir /path/to/qi2labdatastore/proseg/3D

/path/to/proseg --gene-column gene_id -x global_x -y global_y -z global_z --fov-column tile_idx --cell-id-column cell_id --cell-id-unassigned 0 --excluded-genes ^[Bb]lank.*$ --voxel-layers 15 --density-bins 1 --burnin-samples 1000 --samples 2000 --voxel-size 1.0 --burnin-voxel-size 4.0 --enforce-connectivity --diffusion-probability 0.0 --output-spatialdata /path/to/data/qi2labdatastore/proseg/3D/spatialdata_3D.zarr --output-counts /path/to/data/qi2labdatastore/proseg/3D/counts_3D.mtx.gz --output-cell-polygons-layers /path/to/data/qi2labdatastore/proseg/3D/cell_polygons_3D.geojson.gz --output-transcript-metadata /path/to/data/qi2labdatastore/proseg/3D/transcript_metadata_3D.csv.gz /path/to/data/qi2labdatastore/all_tiles_filtered_decoded_features/decoded_features.csv.gz

Documentation

To build the documentation, install using uv sync --group docs. Then execute uv run mkdocs build --clean or uv run mkdocs serve. The documentation is available in your web browser at http://127.0.0.1:8000/.

Pushes to main automatically build and deploy the documentation through the Documentation GitHub Actions workflow. The workflow installs only the documentation dependency group and runs on a standard CPU runner; it does not require CUDA or GPU hardware. Configure the repository's Pages source as GitHub Actions under Settings → Pages.

Testing

The suite consists of unit tests and integration tests. Every test has exactly one of these markers. Run either category with:

uv run pytest -m unit
uv run pytest -m integration

See the testing guidelines for the required assertions and how to classify tests.

The simulation tests require an NVIDIA GPU, the extracted Zenodo sample data, and the default simfish U-FISH weights cached by U-FISH. Pass the extracted dataset directory with --simulation-data-root. See the synthetic-data example for setup instructions.

Standard simulation matrix:

uv run pytest tests/test_simulation_example_pipeline.py -vv \
  --simulation-data-root simulation-data/merfish3d_analysis-simulation

Full repository suite, including the exhaustive simulation matrix:

uv run pytest -vv --run-simulation-exhaustive \
  --simulation-data-root simulation-data/merfish3d_analysis-simulation

The standard simulation matrix uses CUDA device 0 and runs paired affine and SOFIMA preprocessing for every default dataset, axial spacing, and chromatic-aberration setting. The exhaustive mode adds deconvolution-on and deconvolution-off coverage using SOFIMA and synthetic chromatic aberration. It writes measured performance records to tests/data/simulation_performance.json. The tests verify the Zenodo image fingerprints and enforce the documented F1 baselines with an absolute tolerance of 0.02.

About

GPU accelerated post-processing for 2D or 3D imaging spatial transcriptomics data.

Topics

Resources

Contributing

Stars

10 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages