/
_beer_lambert_law.py
86 lines (67 loc) · 2.67 KB
/
_beer_lambert_law.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Authors: Robert Luke <mail@robertluke.net>
# Eric Larson <larson.eric.d@gmail.com>
# Alexandre Gramfort <alexandre.gramfort@inria.fr>
#
# License: BSD (3-clause)
import os.path as op
import numpy as np
from scipy import linalg
from ...io import BaseRaw
from ...io.constants import FIFF
from ...utils import _validate_type
from ..nirs import source_detector_distances, _channel_frequencies,\
_check_channels_ordered
def beer_lambert_law(raw, ppf=0.1):
r"""Convert NIRS optical density data to haemoglobin concentration.
Parameters
----------
raw : instance of Raw
The optical density data.
ppf : float
The partial pathlength factor.
Returns
-------
raw : instance of Raw
The modified raw instance.
"""
raw = raw.copy().load_data()
_validate_type(raw, BaseRaw, 'raw')
freqs = np.unique(_channel_frequencies(raw))
picks = _check_channels_ordered(raw, freqs)
abs_coef = _load_absorption(freqs)
distances = source_detector_distances(raw.info)
for ii in picks[::2]:
EL = abs_coef * distances[ii] * ppf
iEL = linalg.pinv(EL)
raw._data[[ii, ii + 1]] = (raw._data[[ii, ii + 1]].T @ iEL.T).T * 1e-3
# Update channel information
coil_dict = dict(hbo=FIFF.FIFFV_COIL_FNIRS_HBO,
hbr=FIFF.FIFFV_COIL_FNIRS_HBR)
for ki, kind in enumerate(('hbo', 'hbr')):
ch = raw.info['chs'][ii + ki]
ch.update(coil_type=coil_dict[kind], unit=FIFF.FIFF_UNIT_MOL)
raw.rename_channels({
ch['ch_name']: '%s %s' % (ch['ch_name'][:-4], kind)})
return raw
def _load_absorption(freqs):
"""Load molar extinction coefficients."""
# Data from https://omlc.org/spectra/hemoglobin/summary.html
# The text was copied to a text file. The text before and
# after the table was deleted. The the following was run in
# matlab
# extinct_coef=importdata('extinction_coef.txt')
# save('extinction_coef.mat', 'extinct_coef')
#
# Returns data as [[HbO2(freq1), Hb(freq1)],
# [HbO2(freq2), Hb(freq2)]]
from scipy.io import loadmat
from scipy.interpolate import interp1d
extinction_fname = op.join(op.dirname(__file__), '..', '..', 'data',
'extinction_coef.mat')
a = loadmat(extinction_fname)['extinct_coef']
interp_hbo = interp1d(a[:, 0], a[:, 1], kind='linear')
interp_hb = interp1d(a[:, 0], a[:, 2], kind='linear')
ext_coef = np.array([[interp_hbo(freqs[0]), interp_hb(freqs[0])],
[interp_hbo(freqs[1]), interp_hb(freqs[1])]])
abs_coef = ext_coef * 0.2303
return abs_coef