Skip to content

Reading the source

Read firmware, manuals and loader code to explain a timing behaviour seen in the data, or to predict one to test.

Techniques Predict, then test

Studies

Study Date Status Summary
The vitaldb package's loading conventions 2026-10-17 current The vitaldb Python package sets time zero from the tracks loaded, places waveform blocks by rounding their stamps up to a sample, and lets overlapping blocks overwrite each other. Each choice moves or loses samples.
Time zeros and loaded subsets 2026-10-16 current A VitalDB time "from the start" depends on which tracks were loaded: loading a subset moves the zero to that subset's first record, seconds or hours later. The arrhythmia database's annotations count from the full file's zero.
What a BIS-mimic project says about the index's smoothing 2026-10-13 current The openeeg project reproduces the BIS index from the raw EEG and infers each case's smoothing setting: about 80% of its cases come out at 15 s. Its alignment cannot serve as a timing reference.
The SNUADC firmware 2026-10-13 current The public SNUADC firmware explains the board's timing: it sends no time stamps, samples on its 16 MHz crystal, loses time rather than bunching samples after a stall, reads its channels one after another, and truncates its values. A predicted fault at the microsecond counter's wrap was not found in the data.
The PPG hardware delay and the adopted pulse arrival time 2026-10-12 current VitalDB's raw ECG→PPG pulse arrival time is about 0.4 s longer than physiology. Splitting it into a hardware delay (one value for the release; One device delay for the PLETH across the release) and a physiological part needs an adopted value from studies that sampled ECG and PPG on one clock: about 270 ms for anaesthetised adults.

Observations from these studies

Observation Status Summary
About 20 ms of signal lost at every SNUADC reset established At each step-mode reset the acquisition pauses for about 20 ms inside the last record before the new timing, and that time is never sampled: 17.7 ms on the sample count (Signal lost at a SNUADC step-mode correction), once the filler sample is counted. Every record still holds 100 samples, so nothing in the file shows it.
All SNUADC channels share one clock established Every SNUADC waveform track of a case (ECG leads, ART, PLETH, CVP) has the same first stamp, the same record timing and the same corrections. They are stamped together.
Every time is quantised, and fiducials inherit it established A time on a grid of step Δ carries an error of Δ/√12 (1 SD). In VitalDB that is 0.58 ms for a 500 Hz sample, 2.3 ms for BIS EEG, 0.8 ms for the arrhythmia annotations' 1/360 s grid, and up to ±17 ms for PPG fiducials taken on raw samples, which lock to the 33.3 ms frame.
SNUADC sends no time; the recorder stamps by count established The SNUADC board streams samples with no time stamps. Every SNUADC time in VitalDB is the recorder's model of the board's clock: the sample count at the nominal rate, pulled back when it drifts too far.
SNUADC stamps run −0.95 ppm against the sample count established Between corrections each 0.2 s record stamp increment is about 0.19 µs short: stamps run −0.95 ppm from the sample count in 88% of files (both SNUADC modes). It is arithmetic, not clock drift. The other 12% sit between −0.90 and −0.55 ppm.
The BIS index is slow established The BIS index averages 15–60 s of EEG ending about 3 s before its stamp, with half its weight older than 30 s. It cannot time anything faster than about a minute.
The PLETH arrives about 0.4 s late established Raw R-to-PPG-foot pulse arrival time in VitalDB has a median of 0.64–0.71 s, about 0.4 s more than physiology: the monitor's buffering and filtering. One delay fits the whole release: no clusters by setup, SNUADC port or case order (One device delay for the PLETH across the release).
The plethysmogram is built in 30 Hz frames established The SNUADC PLETH waveform comes from the oximeter in 33.3 ms frames, smoothed to 500 Hz. Its content changes once per frame, on the oximeter's own clock, about 0.4 s after the finger.
Time zero depends on the tracks loaded established A file's time zero is its first record of any track. Loading only some tracks moves the zero to their first record: seconds later, and up to hours.
SNUADC channels are read one after another likely The SNUADC firmware reads its 8 channels in turn, about 0.1 ms each, so within one sample the last channel is read up to about 0.8 ms after the first. The channel order is not known.
SNUADC values are truncated to the count below likely The SNUADC firmware truncates each calibrated value instead of rounding it, so every value sits half a count low on average (about 0.5 mmHg for arterial pressure). Values clamp at counts 0 and 1023.
Stamp-based loaders lose samples at overlaps likely Loaders that place samples by their stamps onto a grid overwrite samples where stamps overlap: about 0.48 s at every SNUADC reset, and one sample about every 35 minutes from the stamp arithmetic.
SNUADC has two event inputs open The firmware sends two event-jack flags with every sample. If any case used them, they would be markers on the SNUADC's own clock.

The approach

The idea. Some timing behaviour is written down: in a device's firmware, a manual, or the code that loads the data. Reading it explains a measurement and predicts the next test.

What it gives. Mechanisms: why time is lost at a stall, why channels are skewed, why a loader moves time zero.

How. Find the code path that produces or consumes the time stamps, state what it predicts, and test the prediction in the data.

Pitfalls. The source may not be the version that was deployed, and documentation may describe settings rather than what was used. A source is a hypothesis until the data agree.

Techniques

  • Predict, then test: Turn what a source says into a prediction about the data (a step every 4,295 s, a skew between two channels, a sample lost every 35 minutes) and look for it, with a control; a source that is not borne out is set aside.