Skip to content

SpectraMax: Parse wavelengths as an array; truncate wavelength badges with hover tooltip - #37

Merged
wasimxyz merged 3 commits into
stagingfrom
wa/fixes-20260422
Apr 22, 2026
Merged

SpectraMax: Parse wavelengths as an array; truncate wavelength badges with hover tooltip#37
wasimxyz merged 3 commits into
stagingfrom
wa/fixes-20260422

Conversation

@wasimxyz

@wasimxyz wasimxyz commented Apr 22, 2026

Copy link
Copy Markdown
Member

Summary

Two related improvements to multi-wavelength run metadata:

  1. Standardize SpectraMax wavelength metadata into a wavelengths array, mirroring the Azure 600 Gel Doc shape. SpectraMax .xls files can declare multiple wavelengths (e.g. 750 / 700 / 650 / 600), but we were collapsing them into a single "750 nm, 700 nm, ..." string that couldn't be filtered or color-coded per-wavelength. Metadata now stores numeric strings (["750", "700", "650", "600"]) and the UI owns display formatting.
  2. Collapse the wavelength column in runs tables so rows stay compact when runs have many wavelengths / wavelength colors. Up to maxVisible badges render inline, followed by a +N overflow badge; hovering the cell reveals every badge on a single row in a tooltip.

Changes

Lambda / parser

  • lambda/src/data_hub_lambda/spectramax_plate_reader/utils.py: parse_metadata now returns "wavelengths": list[str] (numeric strings, no nm suffix) instead of "wavelength": str. Return type widened to dict[str, object].
  • Updated unit tests (lambda/tests/spectramax_plate_reader/test_parse_metadata.py) and integration tests (lambda/tests/integration/test_lambda_api.py) to assert the new shape. Added test_four_wavelengths to cover multi-wavelength parsing.

Web app — API

  • web-app/lib/api/instrument-runs.ts: wavelength filter switched from ->>'wavelength' = $value to a JSONB containment check (->'wavelengths' @> '[$value]'::jsonb). getPlateReaderFilterOptions now pulls distinct values from the array via distinctMetadataArrayValues("wavelengths"). Removed "wavelength" from ALLOWED_METADATA_KEYS; "wavelengths" was already allow-listed for the gel doc.

Web app — UI

  • New TruncatedBadges component + sortWavelengths helper in web-app/components/runs/metadata-badges.tsx (re-exported from runs-table/metadata-utils.tsx). Extracted a BadgeRow helper shared with MetadataArrayBadges.
  • plate-reader-runs-table.tsx: column renamed "Wavelength" → "Wavelengths", now renders TruncatedBadges (maxVisible={1}) with per-wavelength colors, and sorts wavelengths numerically (cells + filter dropdown).
  • gel-doc-runs-table.tsx: wavelengths column uses TruncatedBadges (maxVisible={1}, numeric sort); wavelength-colors column uses TruncatedBadges (maxVisible={2}, no sort).
  • run-metadata-badges.tsx: plate reader + gel doc run-detail sections read wavelengths as an array (row label flips between "Wavelength" / "Wavelengths"), applies buildWavelengthColorMap for consistent per-wavelength colors, and sorts numerically.

Breaking changes

  • Metadata schema: SpectraMax runs now write wavelengths: string[] instead of wavelength: string. Existing rows in instrument_runs.metadata still carry the old "wavelength" key and will render as in the wavelengths column until they're reprocessed. No DB migration required (metadata is JSONB), but consumers reading metadata.wavelength for SpectraMax need to switch to metadata.wavelengths.
  • The wavelength filter query param is unchanged externally but now maps to an array containment query server-side — no action needed for clients.

Driveby changes

  • Renamed the plate reader column header "Wavelength" → "Wavelengths" to match the gel doc and the new array shape.
  • Added a reusable sortWavelengths helper (ascending numeric, non-numeric values pushed to end) so the runs table, filter dropdown, and run-detail sections stay consistent.
  • Factored BadgeRow out of MetadataArrayBadges so the tooltip and inline renderers share layout code.

Testing

  • make check-all (ruff, pyright, prettier, eslint, tsc) passes
  • uv run pytest lambda/tests/spectramax_plate_reader/ lambda/tests/integration/ -v passes, including new test_four_wavelengths
  • uv run data-hub-process spectramax <sample.xls> emits "wavelengths": [...] JSON
  • Plate reader runs table: run with 1 wavelength renders as a single badge (no tooltip); run with ≥2 wavelengths renders <first> +N with a hover tooltip showing all wavelengths in ascending numeric order
  • Plate reader wavelength column filter dropdown lists wavelengths in ascending numeric order and filters correctly against the wavelengths array
  • Gel doc runs table: wavelengths column truncates at 1, wavelength-colors column truncates at 2, both surface full lists in the hover tooltip
  • Run detail page (plate reader + gel doc): wavelengths render as individual color-coded badges in ascending numeric order; label reads "Wavelength" for a single value and "Wavelengths" for multiple
  • Reprocess an existing SpectraMax run and verify the runs list, run detail, and filter all pick up the new wavelengths array

Plate reader runs with multiple wavelengths (e.g. 750/700/650/600 nm) were flattened into a single comma-joined `wavelength` field, which meant filter dropdowns and metadata badges couldn't treat each wavelength independently. Switch the parser to emit a `wavelengths` array of numeric strings, mirroring the Azure 600 Gel Doc shape, and update the web app to render, filter, and color-code each wavelength as its own badge. JSONB containment (`@>`) is now used for the wavelength filter, consistent with gel-doc filtering.
@wasimxyz wasimxyz self-assigned this Apr 22, 2026
@vercel

vercel Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
data-hub Ready Ready Preview, Comment Apr 22, 2026 8:48pm

Request Review

@wasimxyz
wasimxyz merged commit 9985c48 into staging Apr 22, 2026
7 checks passed
@wasimxyz
wasimxyz deleted the wa/fixes-20260422 branch April 22, 2026 20:52
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