/** * The BioSemi Status channel. * * Layer 7. BioSemi's ActiveTwo writes BDF files whose last channel is labelled `Status`, and its * 24-bit samples are not a measurement — they are a bit field the amplifier latched at each * sample. The low 16 bits are the parallel trigger input, which is how nearly every ERP * experiment records stimulus onsets. * * Reading that is file access, not analysis. The codes were written by the hardware at * acquisition time, exactly like an EDF+ annotation, and this module only reports what is in the * bytes. Nothing here inspects a biosignal, so event detection remains a non-goal. * * Only the bits BioSemi documents are named. `raw` carries all 24 so a caller with a rig-specific * convention can decode the rest without waiting for this module to learn about it — inventing * meanings for the undocumented ones would be guessing, and a wrong trigger code is worse than * none. */ import type { EdfHeader, EdfRecording, EdfSignal, EdfStatusWord, EdfTriggerEvent, ReadOptions, TriggerSelection } from './types.js'; /** * The `Status` channel of a BDF file, or `undefined` when there is none. * * Returns `undefined` rather than throwing for a plain EDF or a BDF without the channel: a file * having no Status channel is an ordinary fact about the file, not an error. */ export declare function getStatusSignal(header: EdfHeader): EdfSignal | undefined; /** * Decodes one 24-bit Status sample. * * `decodeDigital` sign-extends BDF samples, as it must for a measurement, so bit 23 of a Status * word arrives as a negative number. The bit field is unsigned, so it is masked back before * anything is read out of it. */ export declare function decodeStatusWord(sample: number): EdfStatusWord; /** * Every change of the trigger word in a window, as timed events. * * A parallel trigger is held for as long as the stimulus computer asserts it, so the same code * repeats over many samples. What an experimenter wants is the TRANSITION, which is why this * reports changes rather than samples: one event per change, carrying the code it changed to. * * Code 0 is "no trigger asserted", so a return to 0 is reported as an event with `trigger: 0` * and is easy to filter out. It is reported rather than dropped because the release time is what * gives a trigger its duration. * * TIMES ARE ELAPSED RECORDING TIME, on the one axis the package uses: `t = 0` is the start of * record 0, the same axis `selection.startSeconds`, `chunk.startSeconds` and `segment.startSeconds` * live on. A sample's time is its own record's TRUE onset plus its offset within that record — * never the record index times the record duration. The two agree on a contiguous file and diverge * by the whole gap on an EDF+D one, where the nominal form reported a stimulus at 2 s that the * hardware latched at 10 s (fixed in 0.2.18). * * THE WINDOW IS HONOURED. The scan is record-aligned, because records are the unit of I/O, but a * sample outside `[startSeconds, startSeconds + durationSeconds)` is never reported — it only * updates the running trigger state. Reporting the whole record would place events outside the * window a caller asked for, and, worse, would let the first sample of a record report a * "transition" to a code that was already held long before it. * * At the left edge this reports the code IN FORCE, not only transitions strictly inside: the first * in-window sample always produces an event. That is the same rule a whole-file read already * follows — `t = 0` yields an event for whatever the first sample holds, transition or not — so an * aligned and an unaligned window behave alike. Filter on `trigger` if you only want assertions. * * A GAP IS A LEFT EDGE TOO. The running trigger state does not survive one, and the first * in-window sample of every contiguous run produces an event. `precededByGap` goes on the event * whose tick IS the run's resume instant, and on no other — so a window that begins part-way into * the first record after a gap yields events and none of them carries it. That is 0.3.67's rule, * narrower than the one this said until 0.3.92: the gap precedes the RUN, not whichever sample the * window happened to admit first, which could be a whole record later. Until * 0.3.13 the state carried across, on the reasoning that a code held over a gap should not be * reported twice — but it is not the same observation twice. The records between two segments do * not exist, so what the trigger did in between is unknown, and staying silent asserted that it * did nothing. A file with one code held before and after a five-minute hole returned a SINGLE * event, and a consumer differencing consecutive events read one 308-second epoch out of eight * seconds of recording. * * A contiguous file has exactly one run, so nothing about it changes. */ export declare function readTriggers(recording: EdfRecording, selection: TriggerSelection, options?: ReadOptions): Promise; //# sourceMappingURL=biosemi.d.ts.map