Skip to content

examples: Hubble FITS denoising (train in place on a non-zarr archive)#16

Merged
emfdavid merged 2 commits into
mainfrom
example/hubble-fits-denoising
Jul 15, 2026
Merged

examples: Hubble FITS denoising (train in place on a non-zarr archive)#16
emfdavid merged 2 commits into
mainfrom
example/hubble-fits-denoising

Conversation

@emfdavid

Copy link
Copy Markdown
Owner

What

A cross-domain example that trains in place on an archival format that never was zarr: real Hubble WFC3/IR frames of M16 (the Eagle Nebula) on MAST's public S3 bucket (s3://stpubdata, anonymous), indexed as virtual references (VirtualiZarr → kerchunk.fits → Icechunk) and streamed by insitubatch with no reshard.

  • examples/hubble/data.py — build the virtual-reference store, the denoise_dataset, the chunk/batch transform stages, and the median-filter baseline.
  • examples/hubble/train_torch.py — a tiny residual CNN denoiser.
  • tests/test_hubble.py — a drift guard on the insitubatch-facing wiring.

How it maps onto the engine

  • sample_axis=0 → each FITS frame is one sample (one image = one chunk).
  • Chunk stage (clean_normalize → block-mean Coarsen) runs vectorized on the decode pool; per-sample Gaussian noise lives in the AddNoise batch stage — per the transform-cost contract.
  • Honest framing: because a FITS image is one chunk, this is the streaming-in-place / no-reshard value, not the many-samples-per-chunk decode-amortization of the chunked-zarr examples.
  • The build-time index stack (virtualizarr/kerchunk/astropy) is needed only to build the store; the train hot path is icechunk + numpy (kerchunk never runs at train time).

Result

A short CPU run has the trained denoiser beat the median-filter baseline (real ≈26.4 vs ≈24.7 dB PSNR).

Testing / offline default

--source synthetic (the default) writes a local zarr with the same SCI (frame, y, x) geometry — sharp point sources a median filter can't preserve, plus NaN bad-pixels to exercise the NaN-scrub — so the example runs with no network or FITS stack and backs tests/test_hubble.py. The test asserts the geometry (one frame per chunk), the (noisy, clean) batch labels + NaN scrubbing, the baseline denoises, and the CNN beats the baseline. ruff, mypy, and the tests are green.

Note: MAST's anonymous bucket throttles (HTTP 503) under heavy concurrent read-ahead, so max_inflight is capped low by default; an authenticated/retrying path on AWS would raise it.

🤖 Generated with Claude Code

emfdavid and others added 2 commits July 13, 2026 04:31
A cross-domain example on an archival format that never was zarr. Real Hubble
WFC3/IR frames of M16 on MAST's public S3 bucket are indexed as virtual
references (VirtualiZarr -> kerchunk.fits -> Icechunk) and streamed by
insitubatch with no reshard: sample_axis=0 makes each frame one sample, a
NaN-scrubbing + robust-normalizing chunk stage and a block-mean Coarsen run on
the decode pool, and per-sample Gaussian noise lives in the batch stage. A tiny
residual CNN denoiser beats a median-filter baseline (~26.4 vs ~24.7 dB PSNR).

The build-time index stack (virtualizarr/kerchunk/astropy) is needed only to
build the store; the train hot path is icechunk + numpy.

Ships an offline synthetic source (sharp point sources a median filter can't
keep) as the default -- no network or FITS stack -- which also backs
tests/test_hubble.py, a drift guard on the insitubatch-facing wiring.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The median-filter baseline reached for scipy.ndimage, but scipy is only a
transitive (scikit-learn/bench) dep -- so tests/test_hubble.py would fail on CI
matrix jobs that don't install --extra bench (jax, tf, free-threaded). Replace
it with a vectorized numpy median (edge-padded sliding windows), matching the
pure-numpy baselines in the microscopy/advection examples, so the example and
its test need nothing beyond insitubatch core (+ torch, already guarded).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@emfdavid
emfdavid merged commit d980f32 into main Jul 15, 2026
8 checks passed
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