|
a |
|
b/doc/_includes/channel_interpolation.rst |
|
|
1 |
:orphan: |
|
|
2 |
|
|
|
3 |
Bad channel repair via interpolation |
|
|
4 |
==================================== |
|
|
5 |
|
|
|
6 |
Spherical spline interpolation (EEG) |
|
|
7 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
|
8 |
|
|
|
9 |
.. NOTE: part of this file is included in doc/overview/implementation.rst. |
|
|
10 |
Changes here are reflected there. If you want to link to this content, link |
|
|
11 |
to :ref:`channel-interpolation` to link to that section of the |
|
|
12 |
implementation.rst page. The next line is a target for :start-after: so we |
|
|
13 |
can omit the title from the include: |
|
|
14 |
channel-interpolation-begin-content |
|
|
15 |
|
|
|
16 |
In short, data repair using spherical spline interpolation :footcite:`PerrinEtAl1989` consists of the following steps: |
|
|
17 |
|
|
|
18 |
* Project the good and bad electrodes onto a unit sphere |
|
|
19 |
* Compute a mapping matrix that maps :math:`N` good channels to :math:`M` bad channels |
|
|
20 |
* Use this mapping matrix to compute interpolated data in the bad channels |
|
|
21 |
|
|
|
22 |
Spherical splines assume that the potential :math:`V(\boldsymbol{r_i})` at any point :math:`\boldsymbol{r_i}` on the surface of the sphere can be represented by: |
|
|
23 |
|
|
|
24 |
.. math:: V(\boldsymbol{r_i}) = c_0 + \sum_{j=1}^{N}c_{i}g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_{j}})) |
|
|
25 |
:name: model |
|
|
26 |
|
|
|
27 |
where the :math:`C = (c_{1}, ..., c_{N})^{T}` are constants which must be estimated. The function :math:`g_{m}(\cdot)` of order :math:`m` is given by: |
|
|
28 |
|
|
|
29 |
.. math:: g_{m}(x) = \frac{1}{4 \pi}\sum_{n=1}^{\infty} \frac{2n + 1}{(n(n + 1))^m}P_{n}(x) |
|
|
30 |
|
|
|
31 |
where :math:`P_{n}(x)` are `Legendre polynomials`_ of order :math:`n`. |
|
|
32 |
|
|
|
33 |
.. _Legendre polynomials: https://en.wikipedia.org/wiki/Legendre_polynomials |
|
|
34 |
|
|
|
35 |
To estimate the constants :math:`C`, we must solve the following two equations simultaneously: |
|
|
36 |
|
|
|
37 |
.. math:: G_{ss}C + T_{s}c_0 = X |
|
|
38 |
:name: matrix_form |
|
|
39 |
|
|
|
40 |
.. math:: {T_s}^{T}C = 0 |
|
|
41 |
:name: constraint |
|
|
42 |
|
|
|
43 |
where :math:`G_{ss} \in R^{N \times N}` is a matrix whose entries are :math:`G_{ss}[i, j] = g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_j}))` and :math:`X \in R^{N \times 1}` are the potentials :math:`V(\boldsymbol{r_i})` measured at the good channels. :math:`T_{s} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`N`. Equation :eq:`matrix_form` is the matrix formulation of Equation :eq:`model` and equation :eq:`constraint` is like applying an average reference to the data. From equation :eq:`matrix_form` and :eq:`constraint`, we get: |
|
|
44 |
|
|
|
45 |
.. math:: \begin{bmatrix} c_0 \\ C \end{bmatrix} = {\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1} \begin{bmatrix} 0 \\ X \end{bmatrix} = C_{i}X |
|
|
46 |
:name: estimate_constant |
|
|
47 |
|
|
|
48 |
:math:`C_{i}` is the same as matrix :math:`{\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1}` but with its first column deleted, therefore giving a matrix of dimension :math:`(N + 1) \times N`. |
|
|
49 |
|
|
|
50 |
Now, to estimate the potentials :math:`\hat{X} \in R^{M \times 1}` at the bad channels, we have to do: |
|
|
51 |
|
|
|
52 |
.. math:: \hat{X} = G_{ds}C + T_{d}c_0 |
|
|
53 |
:name: estimate_data |
|
|
54 |
|
|
|
55 |
where :math:`G_{ds} \in R^{M \times N}` computes :math:`g_{m}(\boldsymbol{r_i}, \boldsymbol{r_j})` between the bad and good channels. :math:`T_{d} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`M`. Plugging in equation :eq:`estimate_constant` in :eq:`estimate_data`, we get |
|
|
56 |
|
|
|
57 |
.. math:: \hat{X} = \begin{bmatrix} T_d && G_{ds} \end{bmatrix} \begin{bmatrix} c_0 \\ C \end{bmatrix} = \underbrace{\begin{bmatrix} T_d && G_{ds} \end{bmatrix} C_{i}}_\text{mapping matrix}X |
|
|
58 |
|
|
|
59 |
|
|
|
60 |
To interpolate bad channels, one can simply do: |
|
|
61 |
|
|
|
62 |
>>> evoked.interpolate_bads(reset_bads=False) # doctest: +SKIP |
|
|
63 |
|
|
|
64 |
and the bad channel will be fixed. |
|
|
65 |
|
|
|
66 |
.. target for :end-before: channel-interpolation-end-content |
|
|
67 |
|
|
|
68 |
.. topic:: Examples: |
|
|
69 |
|
|
|
70 |
* :ref:`ex-interpolate-bad-channels` |