william garrow

Work

One program, four artifacts

A research program about making machine learning answer for itself on real-world data. Each artifact was forced by the one before it: a locked corpus, a synthetic stand-in that lied, a medical record coded for the wrong drug.

The easiest task

TLX 14.2 · calm

The hardest task

TLX 83.3 · overload

Synchronized replay, 2x speed. The dot is the gaze; its size is the pupil.

01 · Research

Cognitive load from eye movements

0.783 macro F1 on the real corpus, participants held out

Can eye movements alone flag the moment a task overloads someone? A published model said yes at 0.897, on a synthetic stand-in. I ran the same pipeline on the real COLET corpus with participants held out and got 0.665; the rebuild reached 0.783 with twelve coefficients, and the stand-in's tidy feature story did not survive. The recording here is one participant, calm beside overload, nothing simulated.

python 3.12
$ pip install mat73-reader
>>> from mat73_reader import load
>>> load("data_v3.mat")["Data"]["task"][0]["gaze"][0].shape
(8205, 21)  # participant 1, task 1, unlocked

02 · Open source

mat73-reader

799 tables decoded from a 3.8 GB corpus, on PyPI

COLET ships as MATLAB v7.3 table objects, a format no Python tool could read, so I wrote the decoder. mat73-reader turns them into pandas DataFrames and ships under Apache 2.0. In August I cross-checked its output cell for cell against a second implementation, which is how I found its own empty-table bug, fixed it, and released 0.1.1.

medlit.williamgarrow.com
MedLit patient detail with coded conditions and a structured summary

03 · Health data

MedLit

5 sources ground every claim, 0 model calls on lab values

I built MedLit as graduate research in the same months six companies shipped the same architecture: a patient's FHIR record in, cited plain-language explanations out at a chosen reading level. Retrieval is keyed by the record's own codes, lab verdicts come from reference ranges, and the reading level is measured on the output.

RxCUIThe record saidRxNav says
1116634Tiotropium 18 MCG Inhalation Capsuleticagrelor Oral Tablet
73032Morphine 1mg IVremifentanil
198369Oxybutynin Chloride 5 MG Oral Tablettorsemide 10 MG Oral Tablet

Three of the seven findings from a ten-patient synthetic set. Check the first one yourself, no page of mine in between: RxNav’s raw answer for 1116634 →

04 · Open source

fhir-code-lint

3 miscoded drugs and 4 retired codes, caught before any user saw them

A physician reviewer caught MedLit citing the wrong drug. I went looking for the bug in my pipeline and found none: the synthetic record carried a code that resolves to a different medication. The validator I wrote out of that checks every coded value in a FHIR bundle against RxNav and MedlinePlus Connect, with JSON output and exit codes for CI.

Each artifact exists because the previous one’s data could not be trusted at face value.