Skip to content

Commit

Permalink
Add interpolation of nirs data. Replaces with closest
Browse files Browse the repository at this point in the history
  • Loading branch information
rob-luke committed Mar 12, 2020
1 parent d8db438 commit d77e7f5
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
52 changes: 52 additions & 0 deletions mne/channels/interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,55 @@ def _interpolate_bads_meg(inst, mode='accurate', origin=(0., 0., 0.04),
info_to = pick_info(inst.info, picks_bad)
mapping = _map_meg_channels(info_from, info_to, mode=mode, origin=origin)
_do_interp_dots(inst, mapping, picks_good, picks_bad)


@verbose
def _interpolate_bads_nirs(inst, method='closest', verbose=None):
"""Interpolate bad nirs channels. Simply replaces by closest non bad.
Parameters
----------
inst : mne.io.Raw, mne.Epochs or mne.Evoked
The data to interpolate. Must be preloaded.
method : str
Only the method 'closest' is currently available. This method replaces
each bad channel with the closest non bad channel.
%(verbose)s
"""
from scipy.spatial.distance import pdist, squareform
from mne.preprocessing.nirs import _channel_frequencies, _check_channels_ordered

freqs = np.unique(_channel_frequencies(inst))
# Returns pick of all nirs and ensures channels are correctly ordered
picks_nirs = _check_channels_ordered(inst, freqs)
nirs_ch_names = [inst.info['ch_names'][p] for p in picks_nirs]
bads_nirs = [ch for ch in inst.info['bads'] if ch in nirs_ch_names]

# select the bad meg channel to be interpolated
if len(bads_nirs) == 0:
picks_bad = []
else:
picks_bad = pick_channels(inst.info['ch_names'], bads_nirs,
exclude=[])
bads_mask = [p in picks_bad for p in picks_nirs]

chs = [inst.info['chs'][i] for i in picks_nirs]
locs3d = np.array([ch['loc'][:3] for ch in chs])
dist = pdist(locs3d)
dist = squareform(dist)

for bad in picks_bad:
dists_to_bad = dist[bad]
# Ignore distances to self
dists_to_bad[dists_to_bad == 0] = np.inf
# Ignore distances to other bad channels
dists_to_bad[bads_mask] = np.inf
# Find closest remaining channels
closest_idx = np.where(dists_to_bad == np.amin(dists_to_bad))[0]
# Return the same frequency
closest_idx = closest_idx[bad % 2]
inst._data[bad] = inst._data[closest_idx]

inst.info['bads'] = []

return inst
19 changes: 19 additions & 0 deletions mne/channels/tests/test_interpolation.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,23 @@ def test_interpolation_ctf_comp():
assert raw.info['bads'] == []


@testing.requires_testing_data
def test_interpolation_nirs():
"""Test interpolating bad nirs channels."""
from mne.preprocessing.nirs import optical_density, scalp_coupling_index
from mne.datasets.testing import data_path
from mne.io import read_raw_nirx
from itertools import compress
from mne.channels.interpolation import _interpolate_bads_nirs

fname = op.join(data_path(download=False),
'NIRx', 'nirx_15_2_recording_w_overlap')
raw_intensity = read_raw_nirx(fname, preload=False)
raw_od = optical_density(raw_intensity)
sci = scalp_coupling_index(raw_od)
raw_od.info['bads'] = list(compress(raw_od.ch_names, sci < 0.5))
_interpolate_bads_nirs(raw_od)
assert raw_od.info['bads'] == []


run_tests_if_main()

0 comments on commit d77e7f5

Please sign in to comment.