/** * Channel naming and selection. * * Two real-world facts drive this module. EDF labels are free text that routinely * contain spaces and punctuation ("EEG Fpz-Cz"), and they are not guaranteed to be * unique — CHB-MIT recordings ship two channels both labelled "T8-P8", and some * carry a channel labelled "-". Labels are therefore preserved verbatim in output, * and only disambiguated when the file itself is ambiguous. */ import type { EdfSignal } from '../edf/header.js'; /** * The name of the column the writer puts in front of the channels, which no channel may take. * * Exported and used by the writer rather than repeated there, because the whole point of * reserving it here is that the two cannot drift apart. */ export declare const TIME_COLUMN = "time_s"; export declare class ChannelSelectionError extends Error { constructor(message: string); } /** * Column name for a signal. * * Names are derived from the whole file, not from the current selection, so a given * channel always produces the same column regardless of which channels were asked * for. Duplicated labels get a `_ch` suffix pointing at their position in * the file, which is the only thing that reliably tells them apart. */ export declare function buildColumnNames(signals: readonly EdfSignal[]): Map; /** * Channels whose column name was pushed off their own label to keep the header unique. * * A channel genuinely labelled `T8_ch0` loses that name when another label's disambiguating * suffix wants it, and the resulting column is the one thing in the output that no longer * matches the file. Silence there is what made the collision hard to see in the first place: * the only warning raised was about the *other* label. */ export declare function renamedByCollision(signals: readonly EdfSignal[], columnNames: ReadonlyMap): EdfSignal[]; export interface ChannelSelection { signals: EdfSignal[]; /** Labels that matched more than one channel, so the user knows why they got extras. */ ambiguous: { term: string; matched: EdfSignal[]; }[]; } /** * Resolve a `--channels` specification against the file's signals. * * Matching is case-insensitive on the exact label, with `#` available to * address a specific channel when labels collide. A term that matches nothing is an * error rather than a silent omission: quietly dropping a requested channel would * hand the user a CSV that is missing data they explicitly asked for. */ export declare function selectChannels(signals: readonly EdfSignal[], terms: readonly string[]): ChannelSelection; /** * The label written so that typing it back selects this channel, or null when nothing does. * * Double quotes wherever they survive, since they also show where the label begins and ends * and every documented example is written that way. They do not survive a label containing a * quote of their own, and — less obviously — a shell still expands `$`, a backtick and a * backslash inside them, so `EEG $ref` would arrive as `EEG ` with nothing said. Those go in * single quotes, the one POSIX form with no escapes inside it, where a single quote in the * label closes, escapes and reopens. * * Two labels have no form at all. `--channels` splits its list on commas after the shell has * finished quoting, so no quoting reaches a label with one in it; and a control character * cannot be typed. Both take a position instead, which is what NONPRINTABLE_LABEL already * says for the same two reasons. */ export declare function typeable(label: string): string | null;