Skip to content
Merged
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
7f1cb56
upgrade to zarr 3 library but still write zarr 2 ome zarrs for now
joshua-gould Jul 16, 2026
eb9347f
Save pixel units
joshua-gould Jul 16, 2026
075c74d
fixed saving image
joshua-gould Jul 16, 2026
9f99c3b
fixed saving image
joshua-gould Jul 16, 2026
5fcf591
fixed saving image
joshua-gould Jul 16, 2026
091fa8c
fixed saving image
joshua-gould Jul 16, 2026
c08e4dd
fixed import
joshua-gould Jul 17, 2026
cf75e6e
Save pixel units
joshua-gould Jul 17, 2026
9fa2226
Test if z units are not provided
joshua-gould Jul 17, 2026
fb627be
Pandas<3
joshua-gould Jul 17, 2026
bdda60a
zarr mode
joshua-gould Jul 17, 2026
cc0f9eb
check for null layer key
joshua-gould Jul 17, 2026
8fb7ed0
fixed create zarr array
joshua-gould Jul 17, 2026
98a4b8b
fixed equality check
joshua-gould Jul 17, 2026
3ec4db0
pandas version
joshua-gould Jul 17, 2026
72d226a
fixed anndata layer slicing
joshua-gould Jul 17, 2026
465f461
fixed anndata layer slicing
joshua-gould Jul 17, 2026
27bae79
format crop output
joshua-gould Jul 20, 2026
ba7eb18
spots output
joshua-gould Jul 20, 2026
3fd13d2
spots output
joshua-gould Jul 21, 2026
f45ba78
spots output
joshua-gould Jul 21, 2026
17069bc
rewrite channels
joshua-gould Jul 21, 2026
d915ede
dask cluster
joshua-gould Jul 22, 2026
905b88e
filelock==3.32.0
joshua-gould Jul 22, 2026
60e6658
added cli test for channel subset
joshua-gould Jul 22, 2026
78e7904
Reverted packages
joshua-gould Jul 22, 2026
1cec268
Label chunk size
joshua-gould Jul 22, 2026
13b446d
Label chunk size
joshua-gould Jul 22, 2026
031febb
Label chunk size
joshua-gould Jul 23, 2026
a420bbe
Label chunk size
joshua-gould Jul 23, 2026
2548446
Label chunk size
joshua-gould Jul 23, 2026
eeef0e2
Label chunk size
joshua-gould Jul 23, 2026
ba69b73
Merge branch 'main' of https://github.com/Genentech/scallops into zarr3
joshua-gould Jul 23, 2026
cf93521
output format
joshua-gould Jul 23, 2026
7330c3c
Simplified docker
joshua-gould Jul 23, 2026
9b661bd
updated reqs
joshua-gould Jul 23, 2026
a092310
use maxsize for remove_small_objects
joshua-gould Jul 23, 2026
cdb35f1
scipy==1.18.0
joshua-gould Jul 23, 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
10 changes: 1 addition & 9 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches: [ "main" ]
tags:
- '*' # Matches any tag name
# Optional: Allows manual triggering of the workflow from the GitHub Actions tab
# Allows manual triggering of the workflow from the GitHub Actions tab
workflow_dispatch:

jobs:
Expand All @@ -20,13 +20,6 @@ jobs:
uses: actions/checkout@v6
with:
fetch-depth: 0 # full history so setuptools_scm can resolve the version from tags

- name: Generate package version
id: scm
run: |
pip install --quiet setuptools_scm
echo "version=$(python -m setuptools_scm)" >> "$GITHUB_OUTPUT"

- name: Log in to the GitHub Container Registry
uses: docker/login-action@v3
with:
Expand Down Expand Up @@ -59,6 +52,5 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: SCM_VERSION=${{ steps.scm.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
151 changes: 50 additions & 101 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,136 +1,85 @@
# syntax=docker/dockerfile:1
# SCM_VERSION is passed by:
# - CI: .github/workflows/docker.yml (resolved via python -m setuptools_scm)
# - locally: docker.mk (make -f docker.mk docker / docker-gpu)
# Falls back to 0.0.0+unknown when building directly with docker/podman build .
#
# Base image is always python:${PYTHON_VERSION}-slim-bookworm for both CPU and GPU.
# On GPU builds, CUDA is installed entirely from pip wheels — no nvidia/cuda base needed:
# - tensorflow[and-cuda] brings its own CUDA runtime via nvidia-*-cu12 pip packages
# - torch is installed from PyTorch's CUDA-specific wheel index
# - RAPIDS is installed from NVIDIA's PyPI with cuda-runtime pip dependencies
# A single CUDA_VERSION knob in docker.mk drives RAPIDS_CUDA and TORCH_CUDA_TAG.
#
# GPU build (TF[and-cuda] + RAPIDS + torch from pip):
# make -f docker.mk docker-gpu RAPIDS_VERSION=25.06

# Examples::
# CPU build (default):
# make -f docker.mk docker
# Custom Python version:
# make -f docker.mk docker PYTHON_VERSION=3.11
# docker build --arch amd64 -t scallops .
# GPU build:
# docker build --arch amd64 --build-arg RAPIDS_VERSION=26.6.0 --build-arg RAPIDS_CUDA=cu12 \
# --build-arg TF_CUDA=1 --build-arg TORCH_CUDA=cu126 -t scallops-gpu .
# Custom base image:
# docker build --arch amd64 --build-arg BASE_IMAGE=python:3.13-slim-bookworm -t scallops-custom .

# Only PYTHON_VERSION needs to precede FROM — it is the sole ARG used in the
# FROM instruction. All other build args are declared after FROM.
ARG PYTHON_VERSION=3.12

FROM python:${PYTHON_VERSION}-slim-bookworm
ARG BASE_IMAGE=python:3.12-slim-bookworm
FROM ${BASE_IMAGE}
ARG UV_VERSION=0.11.30
COPY --from=docker.io/astral/uv:${UV_VERSION} /uv /uvx /bin/

ARG PYTHON_VERSION
ARG SCM_VERSION=0.0.0+unknown
ARG TF_VERSION=2.21.0
# IS_GPU is set to 1 by docker.mk for GPU builds, 0 for CPU (default).
ARG IS_GPU=0
# RAPIDS: required when IS_GPU=1, ignored when IS_GPU=0.
# See https://docs.rapids.ai/install for current release versions.
ARG RAPIDS_VERSION
ARG RAPIDS_CUDA=cu12
# TORCH_CUDA_TAG: derived from CUDA_VERSION in docker.mk (e.g. 12.6 → cu126).
# Override via docker.mk if PyTorch doesn't ship a wheel for that exact minor.
ARG TORCH_CUDA_TAG=cu126
ENV IS_GPU=${IS_GPU}

COPY --from=docker.io/astral/uv:latest /uv /uvx /bin/

# build-essential: needed for mahotas/centrosome (requirements.txt) and Cython.
# git: needed to clone ufish from its pinned tag.
RUN apt-get update -qq && \
DEBIAN_FRONTEND=noninteractive apt-get install -qq --no-install-recommends -y \
build-essential \
build-essential \
git && \
rm -rf /var/lib/apt/lists/*

# SETUPTOOLS_SCM_PRETEND_VERSION set as Docker ENV so it propagates into the
# PEP 517 build subprocess that uv spawns (inline shell variables do not
# reliably cross that boundary). Tested: ENV propagation works, inline does not.
ENV UV_SYSTEM_PYTHON=1 \
UV_NO_CACHE=1 \
UV_HTTP_TIMEOUT=300 \
SETUPTOOLS_SCM_PRETEND_VERSION=${SCM_VERSION}
UV_HTTP_TIMEOUT=300

WORKDIR /build

# Print the Python version in use so it's visible in build logs
RUN python3 --version

# Each file is its own layer ordered most→least stable for cache efficiency.

# Pre-install torch from the correct index before ufish/cellpose so their
# dependency resolution sees the right wheel and does not pull a different one.
# GPU: CUDA wheel from PyTorch's CUDA index (bundles its own CUDA libs, no conflict
# with the TF+RAPIDS nvidia-* packages resolved later).
# CPU: explicit cpu-only wheel — default PyPI torch is now CUDA-enabled (+cu13x)
# which is functional but adds ~1-2 GB unnecessarily to a CPU image.
RUN if [ "$IS_GPU" = "1" ]; then \
uv pip install torch \
--index-url https://download.pytorch.org/whl/${TORCH_CUDA_TAG}; \
else \
uv pip install torch \
--index-url https://download.pytorch.org/whl/cpu; \
# install torch?
ARG TORCH="1"
# cu126
ARG TORCH_CUDA="0"
RUN if [ "${TORCH}" = "1" ]; then \
if [ "${TORCH_CUDA}" = "1" ]; then \
uv pip install torch torchvision --index-url https://download.pytorch.org/whl/${TORCH_CUDA}; \
else \
uv pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu; \
fi \
fi

# ufish: git-pinned tag, rarely bumped
COPY requirements.ufish.txt ./
RUN uv pip install -r requirements.ufish.txt
# install ufish?
ARG UFISH="1"
RUN if [ "${UFISH}" = "1" ]; then uv pip install -r requirements.ufish.txt; fi

# cellpose 3.x: declares numpy<2.1 but is runtime-compatible with numpy 2.x;
# separate step so uv resolves against already-installed packages
COPY requirements.cellpose.txt ./
RUN uv pip install -r requirements.cellpose.txt

# extra optional deps: only change when this Dockerfile changes
RUN uv pip install pysam dask-ml miniwdl
ARG CELLPOSE_VERSION="3.1.1.2"
RUN if [ "${CELLPOSE_VERSION}" != "" ]]; then uv pip install cellpose==${CELLPOSE_VERSION}; fi

# core deps: tensorflow is installed in the GPU/CPU step below, so strip it
# here to avoid a redundant re-download from requirements.txt
COPY requirements.txt ./
RUN grep -v '^tensorflow' requirements.txt | uv pip install -r /dev/stdin
# 26.6.0
ARG RAPIDS_VERSION=""
# cu12
ARG RAPIDS_CUDA=""

# TF + RAPIDS: installed together in a single uv pip install so the resolver
# sees all nvidia-*-cu12 constraints simultaneously and finds a consistent
# solution. Separate calls would resolve independently and risk silent
# version conflicts on shared CUDA packages.
# --index-strategy unsafe-best-match: required for RAPIDS transitive deps
# (e.g. libucx-cu12) published by NVIDIA on both pypi.nvidia.com and PyPI at
# different patch versions. This mirrors pip's legacy --extra-index-url
# behaviour which already searched all indexes.
RUN if [ "$IS_GPU" = "1" ]; then \
if [ -z "${RAPIDS_VERSION}" ]; then \
echo "ERROR: RAPIDS_VERSION is required for GPU builds." \
"Pass --build-arg RAPIDS_VERSION=<version>" \
"(see https://docs.rapids.ai/install)" && exit 1; \
fi && \
RUN if [ "${RAPIDS_VERSION}" != "" ]; then \
uv pip install \
tensorflow[and-cuda]==${TF_VERSION} \
cudf-${RAPIDS_CUDA}==${RAPIDS_VERSION} \
cuml-${RAPIDS_CUDA}==${RAPIDS_VERSION} \
dask-cudf-${RAPIDS_CUDA}==${RAPIDS_VERSION} \
--extra-index-url https://pypi.nvidia.com \
--index-strategy unsafe-best-match; \
--extra-index-url https://pypi.nvidia.com; \
fi

ARG TF_VERSION=2.21.0
ARG TF_CUDA="0"
RUN if [ "${TF_CUDA}" = "1" ]; then \
uv pip install tensorflow[and-cuda]==${TF_VERSION}; \
else \
uv pip install tensorflow==${TF_VERSION}; \
fi
# core deps: tensorflow is installed in prior step, so strip it from requirements.txt
COPY requirements.txt ./
RUN grep -v '^tensorflow' requirements.txt | uv pip install -r /dev/stdin

# extra optional deps
RUN uv pip install dask-ml

# --no-deps: all deps already installed above; avoids re-downloading tensorflow.
# SETUPTOOLS_SCM_PRETEND_VERSION (set via ENV above) ensures setuptools_scm
# writes the correct version into _version.py and the wheel metadata.
# PYTHON_VERSION is inferred dynamically from the interpreter so it always
# matches whatever Python the base image ships — no ARG to keep in sync.
COPY . .
RUN [ "${SCM_VERSION}" = "0.0.0+unknown" ] && \
echo "WARNING: SCM_VERSION not set — version will be 0.0.0+unknown. Use 'make -f docker.mk docker' to stamp the correct version." || true && \
uv pip install --no-deps . && \
PYVER=$(python3 -c "import sys; v=sys.version_info; print(f'{v.major}.{v.minor}')") && \
python3 -m compileall -q /usr/local/lib/python${PYVER} >/dev/null 2>&1 || true && \
rm -rf /build

RUN --mount=source=.git,target=.git,type=bind uv pip install --no-cache-dir .
RUN rm -rf /build

ENV AWS_RETRY_MODE=adaptive \
AWS_MAX_ATTEMPTS=10 \
Expand Down
Loading