Skip to content

Dashboard search overhaul, viewer redesign & performance work#29

Merged
aperson30 merged 1 commit into
mainfrom
aditya/dashboard-search-viewer-overhaul
Jun 20, 2026
Merged

Dashboard search overhaul, viewer redesign & performance work#29
aperson30 merged 1 commit into
mainfrom
aditya/dashboard-search-viewer-overhaul

Conversation

@aperson30

Copy link
Copy Markdown
Collaborator

Summary

Frontend-focused overhaul of the dashboard and viewer, plus additive backend perf work. All reuses existing endpoints — no new routes, no utils.py edits.

Dashboard / search

  • Facet-powered filters with live counts via /api/facets
  • New filters from existing metadata: manufacturer, CT phase, site, study year (values discovered from facets, not hardcoded)
  • URL-encoded shareable cohorts + a Copy link button
  • Pagination over results (16/page = 4×4) with Prev/Next, jump-to-page, and Browse all to page the full ~9.9k dataset — only one page in the DOM at a time; thumbnails are loading="lazy"
  • Default grid = fullest-body scans, balanced half tumor / half no-tumor
  • Headline "Organ Classes" stat now derived from the viewer's actual label set (32), not a hardcoded value

Viewer

  • Refined dark UI (panels, sliders, segmented controls, custom checkboxes/chevrons)
  • Inline Organ Statistics panel (per-organ volume + mean HU via /api/mask-data)
  • Low-res-first volume loading with an HD toggle; measured download progress bar
  • Local-first volume loading with HuggingFace fallback (per the maintainer's local-disk rule)
  • View-switch (MPR/Axial/Sag/Cor/3D) layout + camera fixes
  • 3D organ loader restored behind an error boundary; report button now shows feedback instead of failing silently

Upload

  • Client-side pre-inference CT preview (NiiVue, lazy-loaded)

Performance

  • Route code-splitting — dashboard initial JS ~1.6 MB → ~93 KB gzip
  • Viewer-chunk prefetch on hover/idle

Backend (additive, fully fallback-safe)

  • Low-res volume serving via ?res=low on get-main-nifti / get-segmentations (falls back to full res if absent)
  • Cache-Control on volume responses
  • flask-server/scripts/make_lowres.py batch job to generate low-res CT + mask copies

Deploy notes

  • To enable the low-res speedup, run make_lowres.py on the server (needs writable $PANTS_PATH/data + disk headroom). Until then, everything serves full-res exactly as before.
  • nginx-in-front-of-gunicorn (sendfile/range/HTTP2/brotli) is a recommended follow-up but is server-config, not in this PR.

Testing

  • tsc -b clean; 32/32 Vitest tests pass (added unit tests for the search helpers); production build succeeds.
  • Note: the dev checkout ships only metadata.xlsx, so volume/organ-stats/report features that need image data show graceful "unavailable" states locally and will populate on the JHU server.

Dashboard / search:
- Facet-powered filters with live counts via /api/facets
- New filters from existing metadata: manufacturer, CT phase, site, study year
- URL-encoded, shareable/bookmarkable filtered cohorts + copy-link button
- Pagination over results (16/page, 4x4) with prev/next, jump-to-page, and
  "Browse all" to page the full dataset; lazy-loaded thumbnails
- Default grid = fullest-body scans, half tumor / half no-tumor
- Accurate organ-class stat (derived from the viewer's label set)

Viewer:
- Refined dark UI (panels, sliders, segmented controls, checkboxes, chevrons)
- Inline Organ Statistics panel (per-organ volume + mean HU via /api/mask-data)
- Low-res-first volume loading with an HD toggle; measured download progress bar
- Local-first volume loading with HuggingFace fallback
- View-switch (MPR/Axial/Sag/Cor/3D) layout + camera fixes
- 3D organ loader restored behind an error boundary; report-button feedback

Upload:
- Client-side pre-inference CT preview (NiiVue, lazy-loaded)

Performance:
- Route code-splitting (dashboard initial JS ~1.6MB -> ~93KB gzip)
- Viewer-chunk prefetch on hover/idle

Backend (additive, fallback-safe):
- Low-res volume serving via ?res=low on get-main-nifti / get-segmentations
- Cache-Control on volume responses
- scripts/make_lowres.py batch job to generate low-res CT + mask copies
@aperson30 aperson30 merged commit 8ef7cff into main Jun 20, 2026
5 checks passed
# for big full-body scans). Falls back to full res if it hasn't been generated.
if (request.args.get('res') or '').strip().lower() == 'low':
low_path = f"{case_dir}/{Constants.MAIN_NIFTI_FILENAME.replace('.nii.gz', '_lowres.nii.gz')}"
if os.path.exists(low_path):
# overlay stays aligned). Falls back to full res below if it hasn't been generated.
if (request.args.get('res') or '').strip().lower() == 'low':
low_path = nifti_path.replace('.nii.gz', '_lowres.nii.gz')
if os.path.exists(low_path):
if (request.args.get('res') or '').strip().lower() == 'low':
low_path = nifti_path.replace('.nii.gz', '_lowres.nii.gz')
if os.path.exists(low_path):
response = make_response(send_file(low_path, mimetype='application/gzip'))
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.

2 participants