Migrating to 0.3

0.3.0 renamed three functions and changed nothing else. If your recordings are contiguous — every plain EDF and every EDF+C — a find-and-replace is the whole migration.

The change

Three functions were renamed in 0.3.0. Nothing else in the public API changed, and no arithmetic changed.

0.2 0.3
sampleIndexAt gridSampleIndexAt
sampleStartTicks gridSampleStartTicks
sampleStartSeconds gridSampleStartSeconds

Same arguments, same return values, same rounding. They were marked @deprecated in 0.2.62, a release ahead of the change, so an editor pointed at the replacement before it landed.

Why a rename is worth a minor bump

These functions measure the signal’s own sample grid: sample n is the nth sample the file stores for that signal, at n × recordDuration / samplesPerRecord. On a contiguous recording that is also elapsed recording time, and the two ideas are the same number — which is exactly why the difference was easy to miss.

On a discontinuous file they part company. Samples are adjacent in the array across a gap while their times are not, so on a file with a seven-second hole after record 2:

gridSampleStartSeconds(signal, 12, d);   // 3   — the twelfth sample on the grid
// record 3 truly begins at 10 s

Both numbers are correct about different things. The name said neither.

This project has shipped seven separate fixes for one defect: a function deriving a time from the nominal grid while every other function used the record’s true onset. readTriggers reported a stimulus latched at 10 s as 2 s; filterAnnotationsByTime put events in the neighbouring window; mergeChunks could not see a gap; and sampleAt itself shipped with the seventh in 0.2.61 and was fixed in 0.2.68. Each was found late, and each was found because two functions disagreed rather than because one looked wrong. The grid prefix is what stops the seventh: you cannot call gridSampleStartSeconds and believe you asked for elapsed recording time.

The functions themselves were never wrong, and they are not deprecated in favour of nothing — they are the right tool when you have a signal and no recording, which is the whole reason they take no index.

If your file might have gaps

Use the recording-aware forms added in 0.2.61. They take the recording, so a gap is in their arguments:

import { sampleAt, sampleStartTicksOf, sampleStartSecondsOf } from 'edfcore';

sampleAt(recording, eeg.index, 3612.5);           // EdfSampleLocation, or undefined
sampleStartSecondsOf(recording, eeg.index, 940);  // when sample 940 actually starts

sampleAt can return undefined, which the grid form structurally cannot: no sample exists at that instant, because it falls in a gap, before the recording, or after it. Given only a signal and a record duration, gridSampleIndexAt always returns an index — including one past the end of the file.

Both refuse a probed index on a file with gaps rather than guessing. contiguityOf(index) tells you which regime you are in; await buildRecordIndex(recording) is what turns 'unknown' into an answer.

Doing the migration

If your recordings are contiguous — every plain EDF and every EDF+C, which is most files — the rename is the only thing that affects you:

sed -i '' \
  -e 's/\bsampleIndexAt\b/gridSampleIndexAt/g' \
  -e 's/\bsampleStartTicks\b/gridSampleStartTicks/g' \
  -e 's/\bsampleStartSeconds\b/gridSampleStartSeconds/g' \
  $(git ls-files '*.ts' '*.js')

Mind the order if you write your own: sampleStartSeconds is not a prefix of anything here, but sampleStartTicks and sampleStartTicksOf are distinct names and a substring replace would damage the second. The \b word boundaries above are what prevent that.

If you handle EDF+D, treat the rename as a prompt to check each call site. Any place you were converting a time to a sample index, or a sample index to a time, and the file may have gaps, wants the recording-aware form instead. tests/property/timebase.test.ts in the repository shows both regimes side by side against one fixture.

What is not changing

  • No behaviour, anywhere. The 0.3.0 release renamed symbols and nothing else.
  • No other export is removed or renamed.
  • The three entry points, the error hierarchy, and the ByteSource contract are untouched.