Skip to content

Ship all deepcell-types baselines in a single .tar.gz - #12

Merged
xuefei-wang merged 1 commit into
mainfrom
feat/dct-single-baseline-bundle
Jul 30, 2026
Merged

Ship all deepcell-types baselines in a single .tar.gz#12
xuefei-wang merged 1 commit into
mainfrom
feat/dct-single-baseline-bundle

Conversation

@xuefei-wang

Copy link
Copy Markdown
Contributor

Supersedes the per-baseline bundle shape from #11 (nothing was uploaded under those keys, so no served asset is affected).

The three baselines now share one archive, with a subdirectory per baseline under the version-scoped top-level directory:

deepcell-types_baselines_2026-06-30/
  cellsighter/deepcell-types_baseline-cellsighter.pth
  maps/deepcell-types_baseline-maps.pth
  maps/deepcell-types_baseline-maps_stats.npz
  xgboost/deepcell-types_baseline-xgboost.json
  xgboost/deepcell-types_baseline-xgboost.remap.json

models/deepcell-types_baselines_2026-06-30.tar.gz — 646 MB, md5 910840c7caf10fea2c60b66061074471. All three baseline names map to it.

Trade-off

Requesting any single baseline downloads all three. fetch_data caches by filename, so the first request pays the full transfer and the other two are then served from cache with no second download — but a user who only ever wants maps (7 MB of checkpoint) still pulls 646 MB.

The upside is one asset to upload, version, and hash instead of three, and the same atomicity property that motivated #11: maps and xgboost each ship a companion file required at inference, and those can never be fetched into inconsistent states.

_download.py is unchanged — the manifest value is still a list of records, and download_deepcell_types_baseline still returns a list of local paths of length one. deepcell-types unpacks the archive and returns only the requested baseline's subdirectory (vanvalenlab/deepcell-types#47).

Verification

Built deterministically (tar --sort=name --owner=0 --group=0 --numeric-owner --mtime=<fixed> piped through gzip -n), so the pinned hash is reproducible from the same inputs. Every file extracted from the bundle md5-matches the original loose checkpoint.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz

Supersedes the per-baseline bundles from #11 (never uploaded). The three
baselines now share one archive, with a subdirectory per baseline under the
version-scoped top-level directory.

Every baseline name maps to the same asset, so requesting any one downloads
all three (646 MB). `fetch_data` caches by filename, so the other two are
then served from the cache without a second transfer; deepcell-types unpacks
the archive and returns only the requested baseline's subdirectory.

`_download.py` is unchanged -- the value is still a list of records, and it
still returns a list of local paths of length one.

Built deterministically (tar --sort=name, fixed owner/mtime, gzip -n), so
the hash is reproducible from the same inputs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz
@xuefei-wang
xuefei-wang merged commit 65b2153 into main Jul 30, 2026
@xuefei-wang
xuefei-wang deleted the feat/dct-single-baseline-bundle branch July 30, 2026 17:40
xuefei-wang pushed a commit to xuefei-wang/deepcell-types that referenced this pull request Jul 30, 2026
vanvalenlab/deepcell-auth#12 ships all three baselines in a single `.tar.gz`
with a subdirectory per baseline, under one version-scoped top-level
directory (the cellsam layout).

The motivation is atomicity -- `maps` and `xgboost` each ship a companion
file required at inference (`_stats.npz`, `.remap.json`), and as separate
assets those could be fetched into inconsistent states -- plus one asset to
upload, version and hash instead of five. Bundling also compresses the
xgboost booster (1.1 GB of JSON) by ~2.9x, so the baselines go from 1.5 GB
to 646 MB.

`download_baseline_checkpoint` now unpacks the bundle with this package's
path-traversal-safe `extract_archive` -- deliberately not deepcell-auth's,
which calls `extractall` unvetted -- and returns only the requested
baseline's subdirectory, sorted. The public contract is unchanged: still
`list[Path]`, and sorting reproduces the order the loose assets were
declared in (weights before companion).

The cost of one shared archive is that requesting any single baseline
downloads all three. `fetch_data` caches by filename, so the first request
pays the transfer and the other two are then served from cache; verified
end-to-end against the real bundle (three baselines, one transfer).

Extraction is skipped when the bundle directory already exists, matching
cellsam. `fetch_data` still re-checks the archive's pinned hash on every
call, so a corrupt download is caught; a hand-edited extraction directory
is not. A bundle missing the requested baseline's subdirectory, or holding
a plain file in its place, raises a readable error instead of
NotADirectoryError.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz
xuefei-wang added a commit to vanvalenlab/deepcell-types that referenced this pull request Jul 30, 2026
* build: add the deepcell-auth dependency

The shared client's bundled ``asset_manifest.yaml`` becomes the single
source of truth for deepcell-types asset keys and integrity hashes, the
way vanvalenlab/torch-mesmer already consumes it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz

* refactor(utils): move extract_archive into its own module

The next commit deletes this repo's download transport in favour of
deepcell-auth, but ``extract_archive`` stays: deepcell-auth's extractor
calls ``extractall`` without vetting members, so delegating it would drop
the zip-slip / tar-traversal / symlink rejection and the member-count and
size bounds. Move it (and the archive limits it reads) out of ``_auth``
ahead of that deletion, and split its tests out of ``tests/test_auth.py``.

Pure move: no behavior change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz

* refactor(utils): delegate model/baseline/data downloads to deepcell-auth

deepcell-auth's bundled asset_manifest.yaml is now the single source of
truth for deepcell-types asset keys and integrity hashes, so this repo
drops its duplicate registry and its auth transport (`utils/_auth.py`).

The public API is unchanged: `download_model`, `download_baseline_checkpoint`,
`download_training_data`, `list_model_versions` and `list_baseline_names`
keep their signatures, `Path`/`list[Path]` return types, the `ValueError`
on an unknown identifier, and the pointer to Nimbus' upstream weights.
`predict.py` is untouched.

Two details worth flagging:

* The SSL checkpoint's manifest key is `2026-06-23-ptft`, not `2026-06-23`
  (vanvalenlab/deepcell-auth#8 renamed it); the mirrored list follows.
* The 2025 CLIP checkpoints are in the manifest for reproducibility but
  cannot be loaded by this code, so `download_model` rejects them instead
  of handing back a checkpoint that fails at `load_state_dict`.

`tests/test_download_delegation.py` reads the packaged manifest offline and
fails if the mirrored versions/baselines drift from it, which is what would
otherwise surface as a `KeyError` from inside `deepcell_auth` at download
time. The `_auth.py` unit tests go with the module they covered.

Note: deepcell-auth's `fetch_data` is simpler than the transport removed
here -- it hashes only for cache lookup (no post-download integrity check),
writes straight to the final path rather than temp-then-replace, hashes
whole-file rather than chunked, and sets no request timeouts. Adopting it
is the deliberate consolidation trade-off; the safe `extract_archive` was
kept locally rather than delegated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz

* feat(utils): unpack the shared baseline bundle served by deepcell-auth

vanvalenlab/deepcell-auth#12 ships all three baselines in a single `.tar.gz`
with a subdirectory per baseline, under one version-scoped top-level
directory (the cellsam layout).

The motivation is atomicity -- `maps` and `xgboost` each ship a companion
file required at inference (`_stats.npz`, `.remap.json`), and as separate
assets those could be fetched into inconsistent states -- plus one asset to
upload, version and hash instead of five. Bundling also compresses the
xgboost booster (1.1 GB of JSON) by ~2.9x, so the baselines go from 1.5 GB
to 646 MB.

`download_baseline_checkpoint` now unpacks the bundle with this package's
path-traversal-safe `extract_archive` -- deliberately not deepcell-auth's,
which calls `extractall` unvetted -- and returns only the requested
baseline's subdirectory, sorted. The public contract is unchanged: still
`list[Path]`, and sorting reproduces the order the loose assets were
declared in (weights before companion).

The cost of one shared archive is that requesting any single baseline
downloads all three. `fetch_data` caches by filename, so the first request
pays the transfer and the other two are then served from cache; verified
end-to-end against the real bundle (three baselines, one transfer).

Extraction is skipped when the bundle directory already exists, matching
cellsam. `fetch_data` still re-checks the archive's pinned hash on every
call, so a corrupt download is caught; a hand-edited extraction directory
is not. A bundle missing the requested baseline's subdirectory, or holding
a plain file in its place, raises a readable error instead of
NotADirectoryError.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy8eiMVmmQHXRAccKwzAyz

---------

Co-authored-by: xuefei-wang <yuecrew42@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant