eegdash.dataset.channel_positions module#
Positions for iEEG channels whose names are not rows of electrodes.tsv.
A recording’s channels are often named differently from its contacts:
an EDF type word:
POL A3is the contactA3(on004551);a reference suffix:
EEG A1-Refis contactA1against a reference that is not a contact (on004551);a bipolar pair:
RAFA1-RAFA2(on004789, on004809acq-bipolar) orPOL B10-B18(on006910, on006914, on005545) is the difference of two contacts.
MNE-BIDS places only channels named exactly like an electrodes.tsv row, so these channels had no position although both contacts are positioned.
resolve_channel_positions() is the one rule the digest (stored
montages, scripts/ingestions/_montage.py) and the runtime
(fill_missing_positions()) share:
A channel named exactly like a contact is that contact.
Otherwise a name names one contact by lookup only: case and white space are ignored, and a leading
POL/EEGtype word may be dropped. Two contacts that match the same name this way make it ambiguous: no position.<contact>-Refis that contact, whenRefis not itself a contact.A pair
<A>-<B>sits at the midpoint of A and B. Every-is tried as the separator; exactly one split must name two distinct contacts, both positioned. An unknown,n/aor ambiguous endpoint, or several possible splits, leave the channel unpositioned.
The midpoint is in the electrodes’ own coordinate system and units, and the distance between the two contacts is kept with it. Nothing is written back to electrodes.tsv, no contact or anatomy is invented, channel names are not changed and the signal is not re-referenced.
- eegdash.dataset.channel_positions.BIPOLAR_MIDPOINT = 'bipolar_midpoint'
position_sourceof a channel placed at the midpoint of two contacts.
- class eegdash.dataset.channel_positions.ChannelPosition(xyz: tuple[float, float, float], source: str, contacts: tuple[str, ...], contact_distance: float | None = None)[source]
Bases:
objectWhere a channel sits, and which contacts that position comes from.
- source: str
- eegdash.dataset.channel_positions.ELECTRODE_ALIAS = 'electrode_alias'
position_sourceof a channel that names one contact under the lookup rules.
- eegdash.dataset.channel_positions.MEASURED = 'measured'
position_sourceof a channel named exactly like a contact.
- eegdash.dataset.channel_positions.derived_positions(ch_names: Sequence[str], electrodes: Mapping[str, Any]) dict[str, ChannelPosition][source]
resolve_channel_positions()without the exactly named (measured) channels.
- eegdash.dataset.channel_positions.fill_missing_positions(raw, electrodes_tsv: Path, coordsystem_json: Path, datatype: str = 'ieeg') dict[str, dict[str, Any]][source]
Give channels without a position the one the module rules derive.
Only channels with no position are touched; a measured position is never replaced. The contacts are placed as MNE-BIDS places them (same frame, units and transform). The provenance of every filled channel goes to
raw.info["temp"]["derived_positions"].- Returns:
Channel name to its provenance, for the channels this filled.
- Return type:
- eegdash.dataset.channel_positions.read_electrode_table(path: Path, encoding: str | None = None) dict[str, tuple[float, float, float] | None][source]
Every name of an electrodes.tsv with its
(x, y, z),Nonewhenn/a.A name listed twice has no single position, so it maps to
None. A file withoutname/x/y/zcolumns gives{}.
- eegdash.dataset.channel_positions.resolve_channel_positions(ch_names: Sequence[str], electrodes: Mapping[str, Any]) dict[str, ChannelPosition][source]
Position of every channel the module rules place, keyed by channel name.
- Parameters:
ch_names (sequence of str) – Channel names as the data file names them.
electrodes (mapping) – Every electrodes.tsv name to its
(x, y, z), or toNonefor ann/arow. Unpositioned names still count when telling whether a name is ambiguous.
- Returns:
Channel name to
ChannelPosition; channels left out have no position.- Return type: