Skip to content

Commit

Permalink
WIP: Set physical range to digital range for stim channels (mne-tools…
Browse files Browse the repository at this point in the history
…#5160)

* Set physical range to digital range for stim channels (so that the scaling factor is 1)

* Scale up stim channel values if diff between max and min is less than 1

* Apply scaling only to data channels

* Don't scale stim channel for BDF files

* Move scaling up

* Get data index right

* Add GitHub PR and whats_new

* Fix for preload=False

* Add test with small BDF file

* FIX: Use testing

* PEP8
  • Loading branch information
cbrnr authored and larsoner committed Jun 27, 2018
1 parent e4c995b commit c2ad41f
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 7 deletions.
2 changes: 2 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,8 @@ Bug

- Fix bug in :meth:`mne.SourceEstimate.get_peak` and :meth:`mne.VolSourceEstimate.get_peak` when there is only a single time point by `Marijn van Vliet`_

- Fix bug in :func:`mne.io.read_raw_edf` when reading BDF files stimulus channels are now not scaled anymore by `Clemens Brunner`_

API
~~~

Expand Down
4 changes: 2 additions & 2 deletions mne/datasets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
path = _get_path(path, key, name)
# To update the testing or misc dataset, push commits, then make a new
# release on GitHub. Then update the "releases" variable:
releases = dict(testing='0.47', misc='0.3')
releases = dict(testing='0.49', misc='0.3')
# And also update the "hashes['testing']" variable below.

# To update any other dataset, update the data archive itself (upload
Expand Down Expand Up @@ -315,7 +315,7 @@ def _data_path(path=None, force_update=False, update_path=True, download=True,
sample='fc2d5b9eb0a144b1d6ba84dc3b983602',
somato='77a7601948c9e38d2da52446e2eab10f',
spm='9f43f67150e3b694b523a21eb929ea75',
testing='fc64b5cd163ea4dd19d8434a7a6d02be',
testing='52b017611bedbedb22ff9f464e895aa7',
multimodal='26ec847ae9ab80f58f204d09e2c08367',
visual_92_categories=['74f50bbeb65740903eadc229c9fa759f',
'203410a98afc9df9ae8ba9f933370e20'],
Expand Down
15 changes: 11 additions & 4 deletions mne/io/edf/edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,15 +272,22 @@ def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
assert ch_data.shape == (len(ch_data), buf_len)
data[ii, d_sidx:d_eidx] = ch_data.ravel()[r_sidx:r_eidx]

data *= cal.T[idx] # scale
data += offsets[idx] # offset
data *= gains.T[idx] # apply units gain last

# only try to read the stim channel if it's not None and it's
# actually one of the requested channels
idx = np.arange(self.info['nchan'])[idx] # slice -> ints
read_size = len(r_lims) * buf_len
stim_channel_idx = np.where(idx == stim_channel)[0]

if subtype == 'bdf':
# do not scale stim channel (see gh-5160)
stim_idx = np.where(np.arange(self.info['nchan']) == stim_channel)
cal[0, stim_idx[0]] = 1
offsets[stim_idx[0], 0] = 0
gains[0, stim_idx[0]] = 1
data *= cal.T[idx]
data += offsets[idx]
data *= gains.T[idx]

if stim_channel is not None and len(stim_channel_idx) > 0:
if annot and annotmap:
evts = _read_annot(annot, annotmap, sfreq,
Expand Down
Binary file added mne/io/edf/tests/data/test_bdf_stim_channel.bdf
Binary file not shown.
23 changes: 22 additions & 1 deletion mne/io/edf/tests/test_edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
edf_overlap_annot_path = op.join(data_path, 'EDF',
'test_edf_overlapping_annotations.edf')
edf_reduced = op.join(data_path, 'EDF', 'test_reduced.edf')
bdf_stim_channel_path = op.join(data_path, 'BDF', 'test_bdf_stim_channel.bdf')


eog = ['REOG', 'LEOG', 'IEOG']
Expand Down Expand Up @@ -75,11 +76,31 @@ def test_bdf_data():
assert_true((raw_py.info['chs'][63]['loc']).any())


@testing.requires_testing_data
def test_bdf_stim_channel():
"""Test if last channel is detected as STIM by default."""
"""Test BDF stim channel."""
# test if last channel is detected as STIM by default
raw_py = _test_raw_reader(read_raw_edf, input_fname=bdf_path)
assert_true(channel_type(raw_py.info, raw_py.info["nchan"] - 1) == 'stim')

# test BDF file with wrong scaling info in header - this should be ignored
# for BDF stim channels
events = [[242, 0, 4],
[310, 0, 2],
[952, 0, 1],
[1606, 0, 1],
[2249, 0, 1],
[2900, 0, 1],
[3537, 0, 1],
[4162, 0, 1],
[4790, 0, 1]]
raw = read_raw_edf(bdf_stim_channel_path, preload=True)
bdf_events = find_events(raw)
assert_array_equal(events, bdf_events)
raw = read_raw_edf(bdf_stim_channel_path, preload=False)
bdf_events = find_events(raw)
assert_array_equal(events, bdf_events)


@testing.requires_testing_data
def test_edf_overlapping_annotations():
Expand Down

0 comments on commit c2ad41f

Please sign in to comment.