acquisition Level 0 pf-dropped-samples

Dropped samples and clock drift

Symptom. Events drift relative to the data across the recording.

1 claim on this page is unverified. TODO(confirm) marks a specific statement the author has not yet checked against a primary source. Everything else on this page has been reviewed. Treat a marked claim as provisional and go to the cited source rather than quoting the sentence.

Symptom

Events line up with the data at the start of a recording and drift away from it toward the end: an ERP that is sharp in the first block is smeared or delayed in the last; a rhythm that should be time-locked to a stimulus is locked only early on; the number of samples in the file does not equal the sampling rate times the duration the protocol says was recorded; the interval between two markers that should be exactly one second grows or shrinks across the file. In multi-stream recordings (EEG plus eye tracker plus stimulus log) the streams agree at one end and disagree by seconds at the other.

Cause

Two mechanisms, often together. Dropped samples: the acquisition buffer overflows (a busy computer, a slow disk, a wireless link) and a block of samples is lost without a gap being written; every later sample is now earlier in the file than it was in time, by the length of the dropped block, and events timestamped by a separate clock no longer match. Clock drift: two devices with their own oscillators (the amplifier and the stimulus computer) run at slightly different rates; timestamps from one drift relative to samples from the other, linearly with time, by parts per million that add up to tens of milliseconds over an hour (TODO(confirm) the drift magnitude the author wants quoted). A nominal sampling rate that is not the true one produces the same drift.

Detect

  • Compare the sample count with the sampling rate times the recorded duration (from an independent clock: the file’s start and end timestamps, or the stimulus log).
  • Plot the interval between successive periodic events (a fixed-rate stimulus, a clock marker) across the recording: dropped samples show as a jump, drift as a slope.
  • Look for discontinuities in the data at the moment of a drop: an abrupt step in slow channels, a phase jump in a rhythm.
  • In multi-stream files (XDF), inspect the recorded clock offsets between streams; a linear trend is drift, a step is a drop.
  • Run the L0.6 first-look checklist: the sampling-rate and event-count items catch both mechanisms.

Fix

  • Prevent it at acquisition: hardware triggers on the amplifier’s own clock, adequate buffers, a wired link, and a periodic hardware sync pulse recorded in both streams.
  • For drift with a known reference (a sync pulse or periodic marker), resample or linearly rescale the event times to the EEG clock; LSL-style recordings store the offsets needed to do it.
  • For dropped samples that can be located, insert a marked gap (an annotation) rather than silently shifting events, and exclude epochs that overlap the gap; a filter across the gap will ring (see pf-filter-across-boundaries).
  • Record what you found and did in the QC log, and state the correction in the methods; if the drop cannot be located, treat everything after it as unaligned.

Example

Left: two timelines of rest and task annotations over a 2-minute run. S001 alternates about 4.2-s rest and 4.1-s task intervals; S088 alternates 1.38-s rest and 5.12-s task intervals and fits 38 annotations where S001 has 30. Right: annotation onset against index for both runs; S088's onsets rise more slowly and fall further behind S001's with every event.

Real data, no signal processing: the EDF+ headers and annotations of ds-eegbci S088 R03 against S001 R03, as read by MNE. S088’s R03 header reports 128 Hz where S001’s reports 160 Hz (S088’s R01 header says 160 Hz), and its annotation intervals (median rest 1.38 s, task 5.12 s, cycle 6.50 s) differ from S001’s cycle of about 8.3 s; 6.50 s × 160 / 128 = 8.12 s, so the annotations and the header disagree about the clock. This is the catalog’s documented caveat that S088, S089, S092 and S100 carry inconsistent/overlapping event timestamps (community-documented, not stated on the PhysioNet page), and the case the L0.6 exercise asks you to catch. Generated by data/scripts/make_figures.py (ODC-By 1.0).