Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
20 changes: 11 additions & 9 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,39 @@ jobs:
name: Check Style
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: psf/black@stable
with:
src: "biahub"
options: "--check --verbose"
use_pyproject: true # Requires python >3.11
use_pyproject: true
- uses: py-actions/flake8@v2
with:
path: "biahub"
flake8-version: "7.2.0" # Duplicates the version in pyproject.toml
flake8-version: "7.2.0"
- uses: isort/isort-action@v1
with:
isort-version: "6.0.1" # Duplicates the version in pyproject.toml
isort-version: "6.0.1"

test:
name: Run Tests
needs: [style]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
- uses: actions/setup-python@v5
with:
python-version: "3.11"
Comment on lines +37 to 41
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion(if-minor)
astral-sh/setup-uv is on version 7 and we should set the option enable-cache to true. It can help with the heavier dependencies like napari and pytorch.


- name: Install the biahub package
run: |
python -m pip install --upgrade pip
pip install torch torchvision ".[dev]" --extra-index-url https://download.pytorch.org/whl/cpu
run: uv sync --extra dev
env:
UV_EXTRA_INDEX_URL: https://download.pytorch.org/whl/cpu

- name: Test with pytest
run: pytest -v
run: uv run pytest -v
55 changes: 55 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Claude Code Instructions for biahub

## Environment

- **Conda envs**: `/hpc/mydata/$USER/envs/`
- **biautils** (iohub, biahub CLI): `module load anaconda; module load comp_micro; conda activate biautils`
- **neuroglancer**: `conda activate /hpc/mydata/$USER/envs/neuroglancer_iohub`

## Repository Structure

Single package, managed with uv (migration in progress from setuptools).

```
biahub/
├── pyproject.toml # uv-managed project
├── biahub/ # Main package
│ ├── cli/ # Click CLI + Hydra pipeline CLI
│ ├── *.py # Processing modules
│ └── vendor/ # Vendored dependencies
├── settings/ # Example YAML configs
├── tests/
└── plans/ # Migration plans
```

## Reference Data

- **Widefield (Hummingbird)**: `/hpc/projects/intracellular_dashboard/virtual_stain_ft_infected/2026_01_29_A549_H2B_CAAX_DAPI_DENV_ZIKV/`
- **Light-sheet (Mantis)**: `/hpc/projects/intracellular_dashboard/organelle_dynamics/2025_08_26_A549_SEC61_TOMM20_ZIKV/`
- **Test data**: `/hpc/projects/intracellular_dashboard/refactor_biahub/`

## Plans

- `plans/biahub-uv.md` — Migrate packaging from setuptools to uv
- `plans/biahub-cli-refactor.md` — Add Hydra pipeline CLI and config templates

## Code Conventions

- Click for CLI, Pydantic v2 for settings (`extra="forbid"`)
- Absolute imports: `from biahub.X import Y`
- OME-Zarr format via iohub library
- Use absolute HPC paths

## Viewing Data

```bash
# Neuroglancer (preferred)
neuroglancer_view.py /path/to/data.zarr --position A/1/0

# Browser dashboard (nd-embedding-atlas)
python /hpc/mydata/$USER/code/nd-embedding-atlas/scripts/ndimg_view.py /path/to/data.zarr --position A/1/0
```

## Related PRs

- PR #200 (feature/merge-mantis-analysis-template): Do NOT merge
90 changes: 90 additions & 0 deletions plans/biahub-cli-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Plan: Add Hydra pipeline CLI and config templates to biahub

## Goal

Add a Hydra-based pipeline CLI (`biahub-pipeline`) that orchestrates multi-step processing workflows. Config templates define microscope-specific parameters and step sequences. Everything lives inside the existing `biahub` package.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought(non-blocking)
Managed to find this article here about having both Pydantic and Hydra work together for config management. Whether or not it's a good idea... that I don't know.

There's also hydra-zen which automatically and dynamically generates structured configs. There are some options in this area, and it might be a good food for thought.


## Key Decisions

- **Single package**: Hydra CLI and configs live inside `biahub/`, not a separate package
- **Microscope naming**: Configs will be named after the microscope and first objective to specify the type of experiment, which specifies good defaults (e.g., `mantis_63x_1.35`, `hummingbird_20x_0.55`, `dragonfly_20x_0.55`, `dragonfly_63x_1.47`, `hummingbird_63x_1.47`). Each microscope config template will contain a comment section that specifies NA, wavelength, channels.
- **First pipeline**: 4-stage widefield+label-free (convert → reconstruct → register → virtual stain)
- **Logging**: Save resolved YAML configs alongside output data

## Directory Structure (additions)

```
biahub/
├── cli/
│ ├── main.py # Existing Click CLI
│ └── pipeline.py # New Hydra entry point
├── conf/ # Hydra config templates
│ ├── config.yaml # Main defaults
│ ├── microscope/
│ │ ├── mantis_63x_1.35.yaml
│ │ └── hummingbird_63x_1.47.yaml
│ ├── step/
│ │ ├── reconstruct.yaml
│ │ ├── register.yaml
│ │ └── virtual_stain.yaml
│ └── slurm/
│ ├── default.yaml
│ └── gpu.yaml
└── pipeline/ # Step orchestration
├── __init__.py
├── runner.py # Pipeline executor
└── steps.py # Step wrappers (convert, reconstruct, register, etc.)
```

## Entry Point

Add to `pyproject.toml`:
```toml
[project.scripts]
biahub-pipeline = "biahub.cli.pipeline:main"
```

## Usage

```bash
# Run full pipeline
biahub-pipeline microscope=hummingbird_63x_1.47 \
input_path=/data/raw output_path=/data/processed

# Dry run
biahub-pipeline ... dry_run=true

# Skip a step
biahub-pipeline ... steps.virtual_stain=false

# Submit to SLURM with GPU
biahub-pipeline ... slurm=gpu
```

## Pipeline Steps

| Step | Wraps |
|------|-------|
| convert | `iohub convert` |
| reconstruct | `biahub reconstruct` |
| register | `biahub estimate-registration` + `biahub register` |
| virtual_stain | `viscy preprocess` + `viscy predict` |

## Dependencies to Add

```
hydra-core>=1.3
hydra-submitit-launcher>=1.2
omegaconf>=2.3
```

## Reference Data

- **Ground truth**: `/hpc/projects/intracellular_dashboard/virtual_stain_ft_infected/2026_01_29_A549_H2B_CAAX_DAPI_DENV_ZIKV/`
- **Test data**: `/hpc/projects/intracellular_dashboard/refactor_biahub/test_widefield.zarr`
- 2 FOVs from the widefield dataset (channels: DAPI, TXR, BF)

## Validation

1. Run pipeline on test data, compare output structure to ground truth
2. Ensure existing Click CLI (`biahub --help`) still works unchanged
39 changes: 39 additions & 0 deletions plans/biahub-uv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Plan: Migrate biahub packaging from setuptools to uv

## Goal

Convert biahub from setuptools to uv as the package manager. Single package — no workspaces.

## Changes

### 1. Replace build system in pyproject.toml

- Replace `[build-system]` from setuptools to hatchling (uv's default)
- Remove `[tool.setuptools]` and `[tool.setuptools.dynamic]` sections
- Set a static version or use hatch-vcs for versioning
- Keep all existing dependencies, scripts, optional-dependencies unchanged

### 2. Add uv-specific configuration

- Add `[tool.uv]` section if needed (e.g., for git dependency overrides)
- Handle git dependencies (`stitch`, `waveorder`) — may need `[tool.uv.sources]` for these

### 3. Generate lockfile

- Run `uv lock` to generate `uv.lock`
- Add `uv.lock` to version control

### 4. Verify

```bash
uv sync --all-extras
biahub --help
pytest tests/
```

## Notes

- No directory moves — `biahub/` package stays where it is
- All imports unchanged
- Click CLI entry point unchanged
- Existing `settings/` YAML configs unchanged
28 changes: 9 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
[build-system]
requires = ["setuptools >= 61", "setuptools_scm[toml]>=3.4", "wheel"]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "biahub"
version = "0.1.0"
description = "Bioimage analysis hub."
readme = "README.md"
license = { file = "LICENSE" }
requires-python = ">=3.11, <4.0"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo(blocking)
You may want to pin the upper bound to 3.14 (exclusive) as triangle doesn't support python 3.14.


# the dynamically determined project metadata attributes
dynamic = ["version"]

classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
]

# list package dependencies here
dependencies = [
"iohub[tensorstore]>=0.3.0a5,<0.4",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo(blocking)
Let's bump this up to 0.3.0a6 as that version fixes a data loss issue with awkward Dask chunk sizes.

"stitch @ git+https://github.com/ahillsley/stitching@jen",
"stitch",
"matplotlib",
"napari",
"PyQt6",
"napari[all]",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(if-minor)
Wondering about this vs having PyQt6.

napari[all] is currently on PyQt5. biautils and ndutils currently do use PyQt5, but WaveOrder's visual optional dependency (which we are not using) is set to "PyQt6>=6.5,<6.8".

The latest release of PyQt5 was over a year and a half ago. PyQt6 is currently actively maintained though, and napari does explicitly support it.

"natsort",
"numpy",
"markdown",
Expand All @@ -35,7 +32,7 @@ dependencies = [
"submitit",
"torch",
"tqdm",
"waveorder @ git+https://github.com/mehta-lab/waveorder.git",
"waveorder",
"largestinteriorrectangle",
"antspyx",
"pystackreg",
Expand Down Expand Up @@ -76,16 +73,9 @@ doc = [
[project.scripts]
biahub = "biahub.cli.main:cli"

[tool.setuptools]
# explicitly specify the package name
# TODO: is there a better way to do this?
packages = ["biahub"]

# allow use of __file__ to load data files included in the package
zip-safe = false

[tool.setuptools.dynamic]
version = { attr = "biahub.__version__" }
[tool.uv.sources]
stitch = { git = "https://github.com/ahillsley/stitching", branch = "jen" }
waveorder = { git = "https://github.com/mehta-lab/waveorder.git" }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(blocking)
should we pin WaveOrder to a commit or tag? We could also just use the version from PyPI.


[tool.black]
line-length = 95
Expand Down
Loading