Inside the file: surfacing trace metadata and peak amplitudes
An .ab1 file is not just a stream of peak heights and base calls. Buried
inside every ABIF container is a directory of tagged records — instrument model, sample
name, dye set, base-calling mobility file, run timestamp, lane number, operator comments.
Professional viewers like Chromas have always surfaced these in a properties panel. Until
today, sanger-viewer threw them away.
What shipped in Step 9
The ABIF parser now walks the full tag directory and extracts eight metadata fields wherever they are present in the file:
- Sample name —
SMPL1, the label the technician typed into the run software - Instrument —
MCHN1, e.g. "ABI PRISM 310" or "3730xl" - Model —
MODL1, a short 4-character model code - Run date —
BCTS1, the base-calling timestamp string - Dye set —
DyeN1–DyeN4joined with "/", e.g. "Joe/Fam/Tamra/Rox" - Base caller —
PDMF1, the mobility/base-calling file name - Comment —
CMNT1, any free-text annotation - Lane —
LANE1, the capillary or gel lane number
Every field is guarded: if the tag is absent the field is simply undefined
and silently omitted from the panel. The viewer never crashes on missing fields. SCF files,
which carry no ABIF tags, still work fine — they get a version field from the
SCF header and nothing else.
The old loose Record<string, string | number> metadata type has been
replaced with a typed TraceMetadata interface whose fields are all optional.
This caught an existing bug: the old parser fell back to reading PBAS data
instead of returning undefined when MCHN1 was absent.
Per-base peak amplitudes in the tooltip
The hover tooltip now shows the raw channel values at the selected peak position — all four of them, for every base. Before, you saw something like:
#47 A peak:3221 q:58
Now you see:
#47 A peak:3221 q:58 A:1842 C:104 G:219 T:87
Those four numbers are the signal intensities of the A, C, G, and T channels at the exact sample position of the base call. In a clean trace the called base's channel is the dominant one — exactly as you'd expect. When the numbers look off (say the called base has a much lower amplitude than a neighbour channel) that's a useful diagnostic hint that the base call may be wrong.
Implementing this was a small extension to hitTest: once we have the best
matching base index, we know its peak position in sample space, and we can simply index
into each of the four Float32Array channels at that position. The values
are rounded to integers for display.
The metadata panel
A compact panel appears below the sequence panel whenever a trace is loaded and carries at least one piece of metadata. It renders as a two-column grid: label on the left in muted type, value on the right in monospace. If the file carries nothing useful — an SCF with no ABIF tags, or an AB1 that was written without optional fields — the panel stays hidden rather than showing an empty box.
The CSS uses display: grid; grid-template-columns: max-content 1fr on the
row container, with each row using display: contents to participate in the
parent grid. This means label and value columns align cleanly without a table, and long
values wrap gracefully into the right column only.
Typing and testing
The new TraceMetadata interface propagates through the whole stack —
parser return types, TraceData.metadata, the revcomp passthrough, and the
structured-clone transfer to the Web Worker. TypeScript catches any site that tries to
access the old machine key (now instrument).
Seven new Vitest unit tests assert that the 310.ab1 fixture yields a sample name and an
instrument string, that the SCF fixture yields a version and no ABIF fields, and that
absent optional fields are undefined rather than throwing. Four new
Playwright tests confirm the panel is hidden before load, visible (with at least one row)
after loading an AB1, stable after loading an SCF, and that the tooltip text matches the
amplitude pattern A:\d+ C:\d+ G:\d+ T:\d+.
What's next
The metadata panel is intentionally minimal right now — plain text, no icons, no copy-to-clipboard. The next passes will add reverse-complement and strand view improvements, PHRED quality display enhancements, and multi-trace workspace support. Each will land as its own small PR, green CI, updated devlog.