Skip to content

BUG: The calibration factor for some channels is set incorrectly in Nihon Kohden reader #13467

@myd7349

Description

@myd7349

Description of the problem

In EEG, sometimes mastoid electrodes (M1, M2) are used instead of ear electrodes (A1, A2).

In some Nihon Kohden EEG files, electrodes M1 and M2 are included (defined in the .21E file), but A1 and A2 are not. In such cases, the calibration factor for M1 and M2 is set to the calibration factor of the DC channel, rather than the calibration factor of the EEG channel. This results in voltage values much higher than those of the other EEG channels.

The relevant code logic is as follows:

_default_chan_labels = [
"FP1",
"FP2",
"F3",
"F4",
"C3",
"C4",
"P3",
"P4",
"O1",
"O2",
"F7",
"F8",
"T3",
"T4",
"T5",
"T6",
"FZ",
"CZ",
"PZ",
"E",
"PG1",
"PG2",
"A1",
"A2",
"T1",
"T2",
]
_default_chan_labels += [f"X{i}" for i in range(1, 12)]
_default_chan_labels += [f"NA{i}" for i in range(1, 6)]
_default_chan_labels += [f"DC{i:02}" for i in range(1, 33)]
_default_chan_labels += ["BN1", "BN2", "Mark1", "Mark2"]
_default_chan_labels += [f"NA{i}" for i in range(6, 28)]
_default_chan_labels += ["X12/BP1", "X13/BP2", "X14/BP3", "X15/BP4"]
_default_chan_labels += [f"X{i}" for i in range(16, 166)]
_default_chan_labels += ["NA28", "Z"]

def _map_ch_to_specs(ch_name):
unit_mult = 1e-3
phys_min = -12002.9
phys_max = 12002.56
dig_min = -32768
if ch_name.upper() in _default_chan_labels:
idx = _default_chan_labels.index(ch_name.upper())
if (idx < 42 or idx > 73) and idx not in [76, 77]:
unit_mult = 1e-6
phys_min = -3200
phys_max = 3199.902
t_range = phys_max - phys_min
cal = t_range / 65535
offset = phys_min - (dig_min * cal)
out = dict(
unit=unit_mult,
phys_min=phys_min,
phys_max=phys_max,
dig_min=dig_min,
cal=cal,
offset=offset,
)
return out

if ch_name.upper() in _default_chan_labels:

As seen in the code, this part retrieves the index of EEG channels through the _default_chan_labels list and determines whether the channel is an EEG or DC channel. When electrodes not included in _default_chan_labels (e.g., M1, M2) are encountered, the calibration factor for M1 and M2 is treated as that of the DC channel, rather than the EEG channel. This ultimately results in M1 and M2 having much higher voltage values than the other EEG channels when converted to physical values.

Steps to reproduce

Use MNE-Python to open an EEG file that includes M1 and M2, and plot several channels.

# coding: utf-8

from pprint import pprint

from mne.io.nihon import read_raw_nihon

eeg_file_path = r'F:\NKT\EEG2100\DA00100E.EEG'
raw = read_raw_nihon(eeg_file_path, preload=False, encoding='cp936', verbose=False)
raw.pick_channels(("Fp1", "Fp2", "M1", "M2"))

pprint(raw.info["chs"])

raw.plot(block=True)

Output:

NOTE: pick_channels() is a legacy function. New code should use inst.pick(...).
[{'cal': 0.00015625239261476192,
  'ch_name': 'Fp1',
  'coil_type': 1 (FIFFV_COIL_EEG),
  'coord_frame': 4 (FIFFV_COORD_HEAD),
  'kind': 2 (FIFFV_EEG_CH),
  'loc': array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]),
  'logno': 1,
  'range': 6399.902,
  'scanno': 1,
  'unit': 107 (FIFF_UNIT_V),
  'unit_mul': 0 (FIFF_UNITM_NONE)},
 {'cal': 0.00015625239261476192,
  'ch_name': 'Fp2',
  'coil_type': 1 (FIFFV_COIL_EEG),
  'coord_frame': 4 (FIFFV_COORD_HEAD),
  'kind': 2 (FIFFV_EEG_CH),
  'loc': array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]),
  'logno': 2,
  'range': 6399.902,
  'scanno': 2,
  'unit': 107 (FIFF_UNIT_V),
  'unit_mul': 0 (FIFF_UNITM_NONE)},
 {'cal': 4.1657189656019924e-05,
  'ch_name': 'M1',
  'coil_type': 1 (FIFFV_COIL_EEG),
  'coord_frame': 4 (FIFFV_COORD_HEAD),
  'kind': 2 (FIFFV_EEG_CH),
  'loc': array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]),
  'logno': 21,
  'range': 24005.46,
  'scanno': 21,
  'unit': 107 (FIFF_UNIT_V),
  'unit_mul': 0 (FIFF_UNITM_NONE)},
 {'cal': 4.1657189656019924e-05,
  'ch_name': 'M2',
  'coil_type': 1 (FIFFV_COIL_EEG),
  'coord_frame': 4 (FIFFV_COORD_HEAD),
  'kind': 2 (FIFFV_EEG_CH),
  'loc': array([nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]),
  'logno': 22,
  'range': 24005.46,
  'scanno': 22,
  'unit': 107 (FIFF_UNIT_V),
  'unit_mul': 0 (FIFF_UNITM_NONE)}]
Using matplotlib as 2D backend.
Image Image

In Nihon Kohden's review app:

Image

In EDFbrowser(Convert .EEG to .EDF with EDFbrowser):

Image

Link to data

DA00100E.zip

Expected results

The calibration factor of M1 and M2 should be the same as the other EEG channels, and in the plot, their amplitude should be on the same order of magnitude as the other EEG channels.

Actual results

The calibration factor of M1 and M2 is different from the other EEG channels, and in the plot, the amplitude of the M1 and M2 waveforms is excessively large, far exceeding that of the other EEG channels.

Additional information

When a .21E file is present, _map_ch_to_specs should use the electrode definitions from that file instead of _default_chan_labels.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions