Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0d9ef74
updated deps, zarr v3, removed dask, test perf fixes
parashardhapola Jun 24, 2026
e44e575
docstring fixes
parashardhapola Jun 25, 2026
eb4526b
Enhance .gitignore, remove coverage.xml, and update dependencies
parashardhapola Jun 25, 2026
c13d505
Pre-execute vignette notebooks for RTD and fix doc build blockers
parashardhapola Jun 25, 2026
fd50d9b
Update pyproject.toml and uv.lock for Python version compatibility; e…
parashardhapola Jun 25, 2026
a5e54f4
fixes and format
parashardhapola Jun 25, 2026
9d2bc91
Enhance data handling and performance optimizations
parashardhapola Jun 27, 2026
d3cce4b
Add fixture downloading for tests
parashardhapola Jun 27, 2026
51ecb98
Implement fixture creation for 1K PBMC CITE-seq dataset
parashardhapola Jun 27, 2026
36cfb31
removed cmocean
parashardhapola Jun 27, 2026
ac52137
updated docs, tests, misc bug fixes
parashardhapola Jun 28, 2026
0714989
removed stale nbs
parashardhapola Jun 28, 2026
80bbf18
formatted
parashardhapola Jun 28, 2026
2f98505
docs fix
parashardhapola Jun 28, 2026
0264d33
add doublet detection
parashardhapola Jun 28, 2026
263f377
docs and tests and ci updates. py312+ compat
parashardhapola Jun 29, 2026
b5658ef
docs update
parashardhapola Jun 29, 2026
a431225
zarr ci fix
parashardhapola Jun 29, 2026
c1ad415
more version pinning for ci
parashardhapola Jun 29, 2026
46e9465
simplify zarr layout to a single memory-budget rule, unify shard-para…
parashardhapola Jul 1, 2026
29fcfa5
performance improvements, docs update
parashardhapola Jul 2, 2026
a56ba9f
test fix
parashardhapola Jul 2, 2026
8308dbe
Track markers_all_clusters.csv in git for CI.
parashardhapola Jul 2, 2026
1d80788
logging fix
parashardhapola Jul 2, 2026
9fb216b
handling largen features wih blosc
parashardhapola Jul 2, 2026
ff2b4b8
hsnwlib 3.12 fix
parashardhapola Jul 3, 2026
353c5dc
rerun nbs and meld assay fixes
parashardhapola Jul 4, 2026
7b6b668
fix RTD build with cached scATAC outputs
parashardhapola Jul 10, 2026
aa64680
merge improvements
parashardhapola Jul 10, 2026
1a66de0
formatted
parashardhapola Jul 10, 2026
89e86b8
more merge fixes
parashardhapola Jul 10, 2026
7f8bd56
wnn fixes
parashardhapola Jul 11, 2026
f82033a
improved metrics
parashardhapola Jul 11, 2026
d528e78
aaded more tests
parashardhapola Jul 11, 2026
40bd8cc
mapping fixes and added symphony flavour
parashardhapola Jul 11, 2026
f8a2db0
mapping cleanup
parashardhapola Jul 11, 2026
d130cd0
pseudotime fixes
parashardhapola Jul 11, 2026
a39e98b
added modal based remote profiling
parashardhapola Jul 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/codecov.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ignore:
- "scarf/tests/*"
- "tests/*"
- "setup.py"

github_checks: false
Expand Down
18 changes: 7 additions & 11 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,16 @@ on:
jobs:
build:
name: Build distribution
runs-on: ubuntu-22.04
runs-on: ubuntu-26.04

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: 3.11.9
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade setuptools wheel build
python-version: "3.14"
- name: Build a binary wheel and a source tarball
run: python -m build
run: uv build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
Expand All @@ -31,12 +27,12 @@ jobs:
name: Publish to PyPI
needs:
- build
runs-on: ubuntu-22.04
runs-on: ubuntu-26.04
environment:
name: pypi
url: https://pypi.org/p/scarf
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
id-token: write
steps:
- name: Download all the dists
uses: actions/download-artifact@v4
Expand Down
64 changes: 52 additions & 12 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,67 @@ on:

jobs:
test:
runs-on: ${{ matrix.os }}
runs-on: ubuntu-26.04
env:
HNSWLIB_NO_NATIVE: "1"
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, windows-2019]
python-version: [3.11.9]
python-version: ["3.12", "3.13", "3.14"]
resolution: [locked]
include:
- python-version: "3.12"
resolution: lowest-direct
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
- name: Install system build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential libfftw3-dev libmetis-dev
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
- name: Install dependencies (locked)
if: matrix.resolution == 'locked'
run: uv sync --group profiling --extra test --extra extra
- name: Install dependencies (lowest-direct)
if: matrix.resolution == 'lowest-direct'
run: uv pip install --resolution lowest-direct -e ".[test,extra]" --group profiling
- name: Lint and check formatting
if: matrix.resolution == 'locked' && matrix.python-version == '3.12'
run: |
uv run ruff check scarf profiling tests
uv run ruff format --check scarf profiling tests
- name: Type check
if: matrix.resolution == 'locked' && matrix.python-version == '3.12'
run: uv run mypy scarf profiling
- name: Download test fixtures
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install -r requirements_extra.txt
pip install pytest pytest-cov topacedo anndata==0.11.4 pcst_fast
- name: Test with pytest
if [ "${{ matrix.resolution }}" = "lowest-direct" ]; then
uv run --no-sync python -m tests.download_fixtures --with-h5ad
else
uv run python -m tests.download_fixtures --with-h5ad
fi
- name: Test with pytest (parallel)
run: |
pytest --cov=.
if [ "${{ matrix.resolution }}" = "lowest-direct" ]; then
uv run --no-sync pytest \
-n auto \
--dist loadfile \
--cov=scarf \
--cov-report=xml \
--cov-report=term
else
uv run pytest \
-n auto \
--dist loadfile \
--cov=scarf \
--cov-report=xml \
--cov-report=term
fi
- name: Upload coverage to Codecov
if: matrix.resolution == 'locked' && matrix.python-version == '3.14'
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false
31 changes: 29 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,46 @@
__pycache__
build
dist
*.egg-info
scarf.egg-info
scarf_toolkit.egg-info
.venv
.venv*/
.ruff_cache
dask-worker-space
# zarr ":memory:" URL materialized as a local directory by older tests
:memory:
:memory:/
*.ipynb_checkpoints
*.ipynb
!docs/.jupyter_cache/executed/**/base.ipynb
docs/.jupyter_cache/_parallel/
docs/.ipython/
docs/source/vignettes/README.md
docs/source/vignettes/scarf_datasets
docs/source/vignettes/dev
docs/source/vignettes/*.txt
docs/source/vignettes/*.mtx
docs/build/
docs/_build/
docs/jupyter_execute
docs/source/scarf_datasets/
.coverage
coverage.xml
htmlcov/
.pytest_cache
interrogate_badge.svg
scarf/tests/datasets/*
test_data
tests/datasets/*
!tests/datasets/markers_all_clusters.csv
tests/.env
tests/.env.*
benchmarks/.env
benchmarks/.env.*
!benchmarks/.env.example
profiling/.env
profiling/.env.*
!profiling/.env.example
profiling/config.toml
# Generated / local-only run configs (machine grids). Keep LEARNINGS.md + examples.
profiling/layouts/
test_data
10 changes: 5 additions & 5 deletions .readthedocs.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
version: 2

build:
os: ubuntu-22.04
os: ubuntu-26.04
tools:
python: "3.11"
python: "3.14"

python:
install:
- requirements: requirements.txt
- requirements: requirements_extra.txt
- requirements: docs/source/requirements.txt
- method: pip
path: .
extra_requirements:
- extra
- docs

sphinx:
configuration: docs/source/conf.py
Expand Down
29 changes: 10 additions & 19 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
FROM ubuntu:22.04
FROM ubuntu:26.04

RUN apt update -y && apt autoremove -y && apt clean -y && apt autoclean -y && apt upgrade -y
RUN apt install -y wget build-essential git nano
RUN apt install -y wget build-essential git nano curl libfftw3-dev libmetis-dev libtbb-dev

# The following is done to make sure that tzdata package doesnt prompt for timezone during installation
ARG TZ="Europe/Stockholm"
RUN DEBIAN_FRONTEND="noninteractive" TZ=$TZ apt-get -y install tzdata
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone &
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

#Installing dependencies for sgtsne
RUN apt install -y libmetis-dev libtbb-dev libfftw3-dev lib32gcc-7-dev libflann-dev libcilkrts5
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Installing lastest Miniconda3
RUN wget -O miniconda_inst "https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh" && \
bash miniconda_inst -b && \
rm miniconda_inst
WORKDIR /workspace
COPY . /workspace

# Exporting PATH and also saving it in bashrc for next session
# /workspace/bin is so that sgtsne can be found
RUN echo "export PATH=$PATH:/root/miniconda3/bin:/workspace/bin" >> /root/.bashrc
ENV PATH=$PATH:/root/miniconda3/bin:/workspace/bin
RUN uv python install 3.14 && uv sync --extra extra
ENV PATH="/workspace/.venv/bin:$PATH"

# Installing numpy and pybind11 beforehand because sometimes they don't install so well from requirements.txt
RUN pip install --upgrade pip
RUN pip install --no-cache-dir -U numpy pybind11

RUN pip install scarf
RUN echo "export PATH=/workspace/.venv/bin:/workspace/bin:$PATH" >> /root/.bashrc
ENV PATH=/workspace/.venv/bin:/workspace/bin:$PATH
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) [2021], [Dhapola P, Karlsson G]
Copyright (c) 2026, Nygen Analytics AB
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
8 changes: 4 additions & 4 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ exclude .readthedocs.yml
exclude Dockerfile
prune scarf_toolkit.egg-info
prune docs
prune scarf/tests
prune tests
prune profiling
prune scripts
prune .circleci
prune .github
include requirements.txt
include requirements_extra.txt
include VERSION
include pypi_README.rst
include README.md
graft bin
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Scarf

Out-of-core, graph-first workflows for million-cell RNA-seq and CITE-seq.

[![PyPI](https://img.shields.io/pypi/v/scarf.svg)](https://pypi.org/project/scarf)
[![Docs](https://readthedocs.org/projects/scarf/badge/?version=latest)](https://scarf.readthedocs.io)
[![Tests](https://github.com/parashardhapola/scarf/actions/workflows/pytest.yml/badge.svg)](https://github.com/parashardhapola/scarf/actions/workflows/pytest.yml)
[![Coverage](https://codecov.io/gh/parashardhapola/scarf/branch/master/graph/badge.svg?token=ZvJXuYq3pd)](https://codecov.io/gh/parashardhapola/scarf)
[![Downloads](https://pepy.tech/badge/scarf)](https://pepy.tech/project/scarf)

## Installation

Requires Python 3.12+.

```bash
pip install scarf[extra]
```

## Features

- Analyze atlas-scale scRNA-seq on modest hardware (tested up to 4M cells)
- CITE-seq multimodal analysis with WNN and SNN integration
- Zarr-backed chunking for low memory use
- Parallel UMAP and SG-tSNE embeddings
- Harmony batch correction and partial PCA for merged datasets
- Cell projection and label transfer across datasets
- TopACeDo subsampling for representative cell selection
- Hierarchical clustering with interpretable dendrograms

## Quick start

Convert a Cell Ranger `filtered_feature_bc_matrix.h5` to Zarr, then run a minimal scRNA-seq workflow:

```python
import scarf

reader = scarf.CrH5Reader("filtered_feature_bc_matrix.h5")
scarf.CrToZarr(reader, zarr_loc="data.zarr").dump(batch_size=1000)

ds = scarf.DataStore("data.zarr", nthreads=4, min_features_per_cell=10)
ds.filter_cells(attrs=["RNA_nCounts", "RNA_nFeatures"], highs=[15000, 4000], lows=[1000, 500])

ds.mark_hvgs(min_cells=20, top_n=500)
ds.make_graph(feat_key="hvgs", k=11, dims=15, n_centroids=100)
ds.run_umap(n_epochs=250, spread=5, min_dist=1, parallel=True)
ds.run_leiden_clustering(resolution=0.5)

ds.plot_layout(layout_key="RNA_UMAP", color_by="RNA_leiden_cluster")
```

## Documentation

- [Installation guide](https://scarf.readthedocs.io/en/latest/install.html)
- [scRNA-seq tutorial](https://scarf.readthedocs.io/en/latest/vignettes/basic_tutorial_scRNAseq.html)
- [CITE-seq tutorial](https://scarf.readthedocs.io/en/latest/vignettes/multiple_modalities.html)
- [Integration guide](https://scarf.readthedocs.io/en/latest/integration_guide.html)
- [Full API](https://scarf.readthedocs.io/en/latest/api.html)

## Citation

If you use Scarf in your research, please cite [Dhapola et al., Nature Communications (2022)](https://doi.org/10.1038/s41467-022-32097-3).

## Support

Open an [issue on GitHub](https://github.com/parashardhapola/scarf/issues) if you run into problems.
55 changes: 0 additions & 55 deletions README.rst

This file was deleted.

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.32.3
1.0.0
1 change: 1 addition & 0 deletions docs/.jupyter_cache/__version__.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.0.1
Loading
Loading