-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ENH: Convert NIRS raw data to optical density (#6827)
* Initial framework for fnirs raw to optical density conversion * Add optical density to docs * Update mne/preprocessing/tests/test_optical_density.py Co-Authored-By: Eric Larson <[email protected]> * Update mne/preprocessing/tests/test_optical_density.py Co-Authored-By: Eric Larson <[email protected]> * Import testing * Put optical density docs in preprocessing section * Implement optical density conversion * Fix optical density code style issues * Add plotting of optical density data * Add defaults for optical density plotting * Update mne/preprocessing/optical_density.py Co-Authored-By: Eric Larson <[email protected]> * Handle negative intensities in optical density conversion * Add in -1* that was removed in previous commit * Add tests and fix imports for optical density * Add tests for optical density conversion * Use assert_allclose for testing optical density * Update test_optical_density.py * Update mne/preprocessing/_optical_density.py Co-Authored-By: Alexandre Gramfort <[email protected]> * Do not operate in place for optical density * Force data to load and modify test to include preload=False condition
- Loading branch information
Showing
6 changed files
with
117 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -360,6 +360,7 @@ Projections: | |
read_ica | ||
run_ica | ||
corrmap | ||
optical_density | ||
|
||
EEG referencing: | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Authors: Robert Luke <[email protected]> | ||
# Eric Larson <[email protected]> | ||
# | ||
# License: BSD (3-clause) | ||
|
||
from ..io import BaseRaw | ||
from ..io.constants import FIFF | ||
from ..utils import _validate_type, warn | ||
from ..io.pick import _picks_to_idx | ||
|
||
import numpy as np | ||
|
||
|
||
def optical_density(raw): | ||
r"""Convert NIRS raw data to optical density. | ||
Parameters | ||
---------- | ||
raw : instance of Raw | ||
The raw data. | ||
Returns | ||
------- | ||
raw : instance of Raw | ||
The modified raw instance. | ||
""" | ||
raw = raw.copy().load_data() | ||
_validate_type(raw, BaseRaw, 'raw') | ||
picks = _picks_to_idx(raw.info, 'fnirs_raw') | ||
data_means = np.mean(raw.get_data(), axis=1) | ||
|
||
# The devices measure light intensity. Negative light intensities should | ||
# not occur. If they do it is likely due to hardware or movement issues. | ||
# Set all negative values to abs(x), this also has the benefit of ensuring | ||
# that the means are all greater than zero for the division below. | ||
if len(np.where(raw._data[picks] <= 0)[0]) > 0: | ||
warn("Negative intensities encountered. Setting to abs(x)") | ||
raw._data[picks] = np.abs(raw._data[picks]) | ||
|
||
for ii in picks: | ||
raw._data[ii] /= data_means[ii] | ||
np.log(raw._data[ii], out=raw._data[ii]) | ||
raw._data[ii] *= -1 | ||
raw.info['chs'][ii]['coil_type'] = FIFF.FIFFV_COIL_FNIRS_OD | ||
|
||
return raw |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
# Authors: Robert Luke <[email protected]> | ||
# Eric Larson <[email protected]> | ||
# | ||
# License: BSD (3-clause) | ||
|
||
import os.path as op | ||
|
||
from mne.datasets.testing import data_path | ||
from mne.io import read_raw_nirx, BaseRaw | ||
from mne.preprocessing import optical_density | ||
from mne.utils import _validate_type | ||
from mne.datasets import testing | ||
|
||
import pytest as pytest | ||
import numpy as np | ||
from numpy.testing import assert_allclose | ||
|
||
|
||
fname_nirx = op.join(data_path(download=False), | ||
'NIRx', 'nirx_15_2_recording_w_short') | ||
|
||
|
||
@testing.requires_testing_data | ||
def test_optical_density(): | ||
"""Test return type for optical density.""" | ||
raw = read_raw_nirx(fname_nirx, preload=False) | ||
assert 'fnirs_raw' in raw | ||
assert 'fnirs_od' not in raw | ||
raw = optical_density(raw) | ||
_validate_type(raw, BaseRaw, 'raw') | ||
assert 'fnirs_raw' not in raw | ||
assert 'fnirs_od' in raw | ||
|
||
|
||
@testing.requires_testing_data | ||
def test_optical_density_zeromean(): | ||
"""Test that optical density can process zero mean data.""" | ||
raw = read_raw_nirx(fname_nirx, preload=True) | ||
raw._data[4] -= np.mean(raw._data[4]) | ||
with pytest.warns(RuntimeWarning, match='Negative'): | ||
raw = optical_density(raw) | ||
assert 'fnirs_od' in raw | ||
|
||
|
||
@testing.requires_testing_data | ||
def test_optical_density_manual(): | ||
"""Test optical density on known values.""" | ||
test_tol = 0.01 | ||
raw = read_raw_nirx(fname_nirx, preload=True) | ||
# log(1) = 0 | ||
raw._data[4] = np.ones((145)) | ||
# log(0.5)/-1 = 0.69 | ||
# log(1.5)/-1 = -0.40 | ||
test_data = np.tile([0.5, 1.5], 73)[:145] | ||
raw._data[5] = test_data | ||
|
||
od = optical_density(raw) | ||
assert_allclose(od.get_data([4]), 0.) | ||
assert_allclose(od.get_data([5])[0, :2], [0.69, -0.4], atol=test_tol) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters