We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BUG: Compensation channels pick error
While trying to execute `evoked.interpolate_bads()`, I ran into the following error:
```
  mne\channels\interpolation.py", line 190, in _interpolate_bads_meg
    info_to = pick_info(inst.info, picks_bad)

  mne\io\pick.py", line 411, in pick_info
    'channels' % (current_comp, comps_missing))

RuntimeError: Compensation grade 3 has been applied, but compensation channels are missing: ['BG1-2805', 'BG2-2805', 'BG3-2805', 'G11-2805', 'G12-2805', 'G13-2805', 'G22-2805', 'G23-2805', 'P11-2805', 'P13-2805', 'Q11-2805', 'Q13-2805', 'R11-2805', 'R12-2805', 'R13-2805', 'R22-2805', 'R23-2805']
Either remove compensation or pick compensation channels
```
This error seems to be raised automatically when attempting to make any pick that does not include all `ref_meg` channels. I dug a bit into compensation grades, and it seems that it can only be removed for Raw data using the `apply_gradient_compensation(0)` method.

Maybe it would be better to turn this error into a warning? Indeed in my case, compensation channels are not removed from data, the function only attempts to separately pick bad channels to compute interpolation.
Another way could be to always include these channels, similar to the `ref_meg='auto'` argument of `pick_types()`, but I'm not sure it would make sense in every case (especially this one).
Thanks,

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mne/channels/interpolation.py`
Content:
```
1 # Authors: Denis Engemann <denis.engemann@gmail.com>
2 #
3 # License: BSD (3-clause)
4 
5 import numpy as np
6 from numpy.polynomial.legendre import legval
7 from scipy import linalg
8 
9 from ..fixes import einsum
10 from ..utils import logger, warn, verbose
11 from ..io.pick import pick_types, pick_channels, pick_info
12 from ..surface import _normalize_vectors
13 from ..bem import _fit_sphere
14 from ..forward import _map_meg_channels
15 
16 
17 def _calc_g(cosang, stiffness=4, num_lterms=50):
18     """Calculate spherical spline g function between points on a sphere.
19 
20     Parameters
21     ----------
22     cosang : array-like of float, shape(n_channels, n_channels)
23         cosine of angles between pairs of points on a spherical surface. This
24         is equivalent to the dot product of unit vectors.
25     stiffness : float
26         stiffness of the spline.
27     num_lterms : int
28         number of Legendre terms to evaluate.
29 
30     Returns
31     -------
32     G : np.ndrarray of float, shape(n_channels, n_channels)
33         The G matrix.
34     """
35     factors = [(2 * n + 1) / (n ** stiffness * (n + 1) ** stiffness *
36                               4 * np.pi) for n in range(1, num_lterms + 1)]
37     return legval(cosang, [0] + factors)
38 
39 
40 def _make_interpolation_matrix(pos_from, pos_to, alpha=1e-5):
41     """Compute interpolation matrix based on spherical splines.
42 
43     Implementation based on [1]
44 
45     Parameters
46     ----------
47     pos_from : np.ndarray of float, shape(n_good_sensors, 3)
48         The positions to interpoloate from.
49     pos_to : np.ndarray of float, shape(n_bad_sensors, 3)
50         The positions to interpoloate.
51     alpha : float
52         Regularization parameter. Defaults to 1e-5.
53 
54     Returns
55     -------
56     interpolation : np.ndarray of float, shape(len(pos_from), len(pos_to))
57         The interpolation matrix that maps good signals to the location
58         of bad signals.
59 
60     References
61     ----------
62     [1] Perrin, F., Pernier, J., Bertrand, O. and Echallier, JF. (1989).
63         Spherical splines for scalp potential and current density mapping.
64         Electroencephalography Clinical Neurophysiology, Feb; 72(2):184-7.
65     """
66     pos_from = pos_from.copy()
67     pos_to = pos_to.copy()
68 
69     # normalize sensor positions to sphere
70     _normalize_vectors(pos_from)
71     _normalize_vectors(pos_to)
72 
73     # cosine angles between source positions
74     cosang_from = pos_from.dot(pos_from.T)
75     cosang_to_from = pos_to.dot(pos_from.T)
76     G_from = _calc_g(cosang_from)
77     G_to_from = _calc_g(cosang_to_from)
78 
79     if alpha is not None:
80         G_from.flat[::len(G_from) + 1] += alpha
81 
82     n_channels = G_from.shape[0]  # G_from should be square matrix
83     C = np.r_[np.c_[G_from, np.ones((n_channels, 1))],
84               np.c_[np.ones((1, n_channels)), 0]]
85     C_inv = linalg.pinv(C)
86 
87     interpolation = np.c_[G_to_from,
88                           np.ones((G_to_from.shape[0], 1))].dot(C_inv[:, :-1])
89     return interpolation
90 
91 
92 def _do_interp_dots(inst, interpolation, goods_idx, bads_idx):
93     """Dot product of channel mapping matrix to channel data."""
94     from ..io.base import BaseRaw
95     from ..epochs import BaseEpochs
96     from ..evoked import Evoked
97 
98     if isinstance(inst, (BaseRaw, Evoked)):
99         inst._data[bads_idx] = interpolation.dot(inst._data[goods_idx])
100     elif isinstance(inst, BaseEpochs):
101         inst._data[:, bads_idx, :] = einsum(
102             'ij,xjy->xiy', interpolation, inst._data[:, goods_idx, :])
103     else:
104         raise ValueError('Inputs of type {0} are not supported'
105                          .format(type(inst)))
106 
107 
108 @verbose
109 def _interpolate_bads_eeg(inst, verbose=None):
110     """Interpolate bad EEG channels.
111 
112     Operates in place.
113 
114     Parameters
115     ----------
116     inst : mne.io.Raw, mne.Epochs or mne.Evoked
117         The data to interpolate. Must be preloaded.
118     """
119     bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool)
120     goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool)
121 
122     picks = pick_types(inst.info, meg=False, eeg=True, exclude=[])
123     inst.info._check_consistency()
124     bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks]
125 
126     if len(picks) == 0 or bads_idx.sum() == 0:
127         return
128 
129     goods_idx[picks] = True
130     goods_idx[bads_idx] = False
131 
132     pos = inst._get_channel_positions(picks)
133 
134     # Make sure only EEG are used
135     bads_idx_pos = bads_idx[picks]
136     goods_idx_pos = goods_idx[picks]
137 
138     pos_good = pos[goods_idx_pos]
139     pos_bad = pos[bads_idx_pos]
140 
141     # test spherical fit
142     radius, center = _fit_sphere(pos_good)
143     distance = np.sqrt(np.sum((pos_good - center) ** 2, 1))
144     distance = np.mean(distance / radius)
145     if np.abs(1. - distance) > 0.1:
146         warn('Your spherical fit is poor, interpolation results are '
147              'likely to be inaccurate.')
148 
149     logger.info('Computing interpolation matrix from {0} sensor '
150                 'positions'.format(len(pos_good)))
151 
152     interpolation = _make_interpolation_matrix(pos_good, pos_bad)
153 
154     logger.info('Interpolating {0} sensors'.format(len(pos_bad)))
155     _do_interp_dots(inst, interpolation, goods_idx, bads_idx)
156 
157 
158 @verbose
159 def _interpolate_bads_meg(inst, mode='accurate', verbose=None):
160     """Interpolate bad channels from data in good channels.
161 
162     Parameters
163     ----------
164     inst : mne.io.Raw, mne.Epochs or mne.Evoked
165         The data to interpolate. Must be preloaded.
166     mode : str
167         Either `'accurate'` or `'fast'`, determines the quality of the
168         Legendre polynomial expansion used for interpolation. `'fast'` should
169         be sufficient for most applications.
170     verbose : bool, str, int, or None
171         If not None, override default verbose level (see :func:`mne.verbose`
172         and :ref:`Logging documentation <tut_logging>` for more).
173     """
174     picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])
175     picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')
176     meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]
177     bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]
178 
179     # select the bad meg channel to be interpolated
180     if len(bads_meg) == 0:
181         picks_bad = []
182     else:
183         picks_bad = pick_channels(inst.info['ch_names'], bads_meg,
184                                   exclude=[])
185 
186     # return without doing anything if there are no meg channels
187     if len(picks_meg) == 0 or len(picks_bad) == 0:
188         return
189     info_from = pick_info(inst.info, picks_good)
190     info_to = pick_info(inst.info, picks_bad)
191     mapping = _map_meg_channels(info_from, info_to, mode=mode)
192     _do_interp_dots(inst, mapping, picks_good, picks_bad)
193
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mne/channels/interpolation.py b/mne/channels/interpolation.py
--- a/mne/channels/interpolation.py
+++ b/mne/channels/interpolation.py
@@ -171,8 +171,10 @@
         If not None, override default verbose level (see :func:`mne.verbose`
         and :ref:`Logging documentation <tut_logging>` for more).
     """
-    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])
-    picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')
+    picks_meg = pick_types(inst.info, meg=True, eeg=False,
+                           ref_meg=True, exclude=[])
+    picks_good = pick_types(inst.info, meg=True, eeg=False,
+                            ref_meg=True, exclude='bads')
     meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]
     bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]
 
@@ -186,7 +188,9 @@
     # return without doing anything if there are no meg channels
     if len(picks_meg) == 0 or len(picks_bad) == 0:
         return
-    info_from = pick_info(inst.info, picks_good)
-    info_to = pick_info(inst.info, picks_bad)
+    inst_info = inst.info.copy()
+    inst_info['comps'] = []
+    info_from = pick_info(inst_info, picks_good)
+    info_to = pick_info(inst_info, picks_bad)
     mapping = _map_meg_channels(info_from, info_to, mode=mode)
     _do_interp_dots(inst, mapping, picks_good, picks_bad)

{"golden_diff": "diff --git a/mne/channels/interpolation.py b/mne/channels/interpolation.py\n--- a/mne/channels/interpolation.py\n+++ b/mne/channels/interpolation.py\n@@ -171,8 +171,10 @@\n         If not None, override default verbose level (see :func:`mne.verbose`\n         and :ref:`Logging documentation <tut_logging>` for more).\n     \"\"\"\n-    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])\n-    picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')\n+    picks_meg = pick_types(inst.info, meg=True, eeg=False,\n+                           ref_meg=True, exclude=[])\n+    picks_good = pick_types(inst.info, meg=True, eeg=False,\n+                            ref_meg=True, exclude='bads')\n     meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]\n     bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]\n \n@@ -186,7 +188,9 @@\n     # return without doing anything if there are no meg channels\n     if len(picks_meg) == 0 or len(picks_bad) == 0:\n         return\n-    info_from = pick_info(inst.info, picks_good)\n-    info_to = pick_info(inst.info, picks_bad)\n+    inst_info = inst.info.copy()\n+    inst_info['comps'] = []\n+    info_from = pick_info(inst_info, picks_good)\n+    info_to = pick_info(inst_info, picks_bad)\n     mapping = _map_meg_channels(info_from, info_to, mode=mode)\n     _do_interp_dots(inst, mapping, picks_good, picks_bad)\n", "issue": "BUG: Compensation channels pick error\nWhile trying to execute `evoked.interpolate_bads()`, I ran into the following error:\r\n```\r\n  mne\\channels\\interpolation.py\", line 190, in _interpolate_bads_meg\r\n    info_to = pick_info(inst.info, picks_bad)\r\n\r\n  mne\\io\\pick.py\", line 411, in pick_info\r\n    'channels' % (current_comp, comps_missing))\r\n\r\nRuntimeError: Compensation grade 3 has been applied, but compensation channels are missing: ['BG1-2805', 'BG2-2805', 'BG3-2805', 'G11-2805', 'G12-2805', 'G13-2805', 'G22-2805', 'G23-2805', 'P11-2805', 'P13-2805', 'Q11-2805', 'Q13-2805', 'R11-2805', 'R12-2805', 'R13-2805', 'R22-2805', 'R23-2805']\r\nEither remove compensation or pick compensation channels\r\n```\r\nThis error seems to be raised automatically when attempting to make any pick that does not include all `ref_meg` channels. I dug a bit into compensation grades, and it seems that it can only be removed for Raw data using the `apply_gradient_compensation(0)` method.\r\n\r\nMaybe it would be better to turn this error into a warning? Indeed in my case, compensation channels are not removed from data, the function only attempts to separately pick bad channels to compute interpolation.\r\nAnother way could be to always include these channels, similar to the `ref_meg='auto'` argument of `pick_types()`, but I'm not sure it would make sense in every case (especially this one).\r\nThanks,\n", "before_files": [{"content": "# Authors: Denis Engemann <denis.engemann@gmail.com>\n#\n# License: BSD (3-clause)\n\nimport numpy as np\nfrom numpy.polynomial.legendre import legval\nfrom scipy import linalg\n\nfrom ..fixes import einsum\nfrom ..utils import logger, warn, verbose\nfrom ..io.pick import pick_types, pick_channels, pick_info\nfrom ..surface import _normalize_vectors\nfrom ..bem import _fit_sphere\nfrom ..forward import _map_meg_channels\n\n\ndef _calc_g(cosang, stiffness=4, num_lterms=50):\n    \"\"\"Calculate spherical spline g function between points on a sphere.\n\n    Parameters\n    ----------\n    cosang : array-like of float, shape(n_channels, n_channels)\n        cosine of angles between pairs of points on a spherical surface. This\n        is equivalent to the dot product of unit vectors.\n    stiffness : float\n        stiffness of the spline.\n    num_lterms : int\n        number of Legendre terms to evaluate.\n\n    Returns\n    -------\n    G : np.ndrarray of float, shape(n_channels, n_channels)\n        The G matrix.\n    \"\"\"\n    factors = [(2 * n + 1) / (n ** stiffness * (n + 1) ** stiffness *\n                              4 * np.pi) for n in range(1, num_lterms + 1)]\n    return legval(cosang, [0] + factors)\n\n\ndef _make_interpolation_matrix(pos_from, pos_to, alpha=1e-5):\n    \"\"\"Compute interpolation matrix based on spherical splines.\n\n    Implementation based on [1]\n\n    Parameters\n    ----------\n    pos_from : np.ndarray of float, shape(n_good_sensors, 3)\n        The positions to interpoloate from.\n    pos_to : np.ndarray of float, shape(n_bad_sensors, 3)\n        The positions to interpoloate.\n    alpha : float\n        Regularization parameter. Defaults to 1e-5.\n\n    Returns\n    -------\n    interpolation : np.ndarray of float, shape(len(pos_from), len(pos_to))\n        The interpolation matrix that maps good signals to the location\n        of bad signals.\n\n    References\n    ----------\n    [1] Perrin, F., Pernier, J., Bertrand, O. and Echallier, JF. (1989).\n        Spherical splines for scalp potential and current density mapping.\n        Electroencephalography Clinical Neurophysiology, Feb; 72(2):184-7.\n    \"\"\"\n    pos_from = pos_from.copy()\n    pos_to = pos_to.copy()\n\n    # normalize sensor positions to sphere\n    _normalize_vectors(pos_from)\n    _normalize_vectors(pos_to)\n\n    # cosine angles between source positions\n    cosang_from = pos_from.dot(pos_from.T)\n    cosang_to_from = pos_to.dot(pos_from.T)\n    G_from = _calc_g(cosang_from)\n    G_to_from = _calc_g(cosang_to_from)\n\n    if alpha is not None:\n        G_from.flat[::len(G_from) + 1] += alpha\n\n    n_channels = G_from.shape[0]  # G_from should be square matrix\n    C = np.r_[np.c_[G_from, np.ones((n_channels, 1))],\n              np.c_[np.ones((1, n_channels)), 0]]\n    C_inv = linalg.pinv(C)\n\n    interpolation = np.c_[G_to_from,\n                          np.ones((G_to_from.shape[0], 1))].dot(C_inv[:, :-1])\n    return interpolation\n\n\ndef _do_interp_dots(inst, interpolation, goods_idx, bads_idx):\n    \"\"\"Dot product of channel mapping matrix to channel data.\"\"\"\n    from ..io.base import BaseRaw\n    from ..epochs import BaseEpochs\n    from ..evoked import Evoked\n\n    if isinstance(inst, (BaseRaw, Evoked)):\n        inst._data[bads_idx] = interpolation.dot(inst._data[goods_idx])\n    elif isinstance(inst, BaseEpochs):\n        inst._data[:, bads_idx, :] = einsum(\n            'ij,xjy->xiy', interpolation, inst._data[:, goods_idx, :])\n    else:\n        raise ValueError('Inputs of type {0} are not supported'\n                         .format(type(inst)))\n\n\n@verbose\ndef _interpolate_bads_eeg(inst, verbose=None):\n    \"\"\"Interpolate bad EEG channels.\n\n    Operates in place.\n\n    Parameters\n    ----------\n    inst : mne.io.Raw, mne.Epochs or mne.Evoked\n        The data to interpolate. Must be preloaded.\n    \"\"\"\n    bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool)\n    goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool)\n\n    picks = pick_types(inst.info, meg=False, eeg=True, exclude=[])\n    inst.info._check_consistency()\n    bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks]\n\n    if len(picks) == 0 or bads_idx.sum() == 0:\n        return\n\n    goods_idx[picks] = True\n    goods_idx[bads_idx] = False\n\n    pos = inst._get_channel_positions(picks)\n\n    # Make sure only EEG are used\n    bads_idx_pos = bads_idx[picks]\n    goods_idx_pos = goods_idx[picks]\n\n    pos_good = pos[goods_idx_pos]\n    pos_bad = pos[bads_idx_pos]\n\n    # test spherical fit\n    radius, center = _fit_sphere(pos_good)\n    distance = np.sqrt(np.sum((pos_good - center) ** 2, 1))\n    distance = np.mean(distance / radius)\n    if np.abs(1. - distance) > 0.1:\n        warn('Your spherical fit is poor, interpolation results are '\n             'likely to be inaccurate.')\n\n    logger.info('Computing interpolation matrix from {0} sensor '\n                'positions'.format(len(pos_good)))\n\n    interpolation = _make_interpolation_matrix(pos_good, pos_bad)\n\n    logger.info('Interpolating {0} sensors'.format(len(pos_bad)))\n    _do_interp_dots(inst, interpolation, goods_idx, bads_idx)\n\n\n@verbose\ndef _interpolate_bads_meg(inst, mode='accurate', verbose=None):\n    \"\"\"Interpolate bad channels from data in good channels.\n\n    Parameters\n    ----------\n    inst : mne.io.Raw, mne.Epochs or mne.Evoked\n        The data to interpolate. Must be preloaded.\n    mode : str\n        Either `'accurate'` or `'fast'`, determines the quality of the\n        Legendre polynomial expansion used for interpolation. `'fast'` should\n        be sufficient for most applications.\n    verbose : bool, str, int, or None\n        If not None, override default verbose level (see :func:`mne.verbose`\n        and :ref:`Logging documentation <tut_logging>` for more).\n    \"\"\"\n    picks_meg = pick_types(inst.info, meg=True, eeg=False, exclude=[])\n    picks_good = pick_types(inst.info, meg=True, eeg=False, exclude='bads')\n    meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]\n    bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]\n\n    # select the bad meg channel to be interpolated\n    if len(bads_meg) == 0:\n        picks_bad = []\n    else:\n        picks_bad = pick_channels(inst.info['ch_names'], bads_meg,\n                                  exclude=[])\n\n    # return without doing anything if there are no meg channels\n    if len(picks_meg) == 0 or len(picks_bad) == 0:\n        return\n    info_from = pick_info(inst.info, picks_good)\n    info_to = pick_info(inst.info, picks_bad)\n    mapping = _map_meg_channels(info_from, info_to, mode=mode)\n    _do_interp_dots(inst, mapping, picks_good, picks_bad)\n", "path": "mne/channels/interpolation.py"}], "after_files": [{"content": "# Authors: Denis Engemann <denis.engemann@gmail.com>\n#\n# License: BSD (3-clause)\n\nimport numpy as np\nfrom numpy.polynomial.legendre import legval\nfrom scipy import linalg\n\nfrom ..fixes import einsum\nfrom ..utils import logger, warn, verbose\nfrom ..io.pick import pick_types, pick_channels, pick_info\nfrom ..surface import _normalize_vectors\nfrom ..bem import _fit_sphere\nfrom ..forward import _map_meg_channels\n\n\ndef _calc_g(cosang, stiffness=4, num_lterms=50):\n    \"\"\"Calculate spherical spline g function between points on a sphere.\n\n    Parameters\n    ----------\n    cosang : array-like of float, shape(n_channels, n_channels)\n        cosine of angles between pairs of points on a spherical surface. This\n        is equivalent to the dot product of unit vectors.\n    stiffness : float\n        stiffness of the spline.\n    num_lterms : int\n        number of Legendre terms to evaluate.\n\n    Returns\n    -------\n    G : np.ndrarray of float, shape(n_channels, n_channels)\n        The G matrix.\n    \"\"\"\n    factors = [(2 * n + 1) / (n ** stiffness * (n + 1) ** stiffness *\n                              4 * np.pi) for n in range(1, num_lterms + 1)]\n    return legval(cosang, [0] + factors)\n\n\ndef _make_interpolation_matrix(pos_from, pos_to, alpha=1e-5):\n    \"\"\"Compute interpolation matrix based on spherical splines.\n\n    Implementation based on [1]\n\n    Parameters\n    ----------\n    pos_from : np.ndarray of float, shape(n_good_sensors, 3)\n        The positions to interpoloate from.\n    pos_to : np.ndarray of float, shape(n_bad_sensors, 3)\n        The positions to interpoloate.\n    alpha : float\n        Regularization parameter. Defaults to 1e-5.\n\n    Returns\n    -------\n    interpolation : np.ndarray of float, shape(len(pos_from), len(pos_to))\n        The interpolation matrix that maps good signals to the location\n        of bad signals.\n\n    References\n    ----------\n    [1] Perrin, F., Pernier, J., Bertrand, O. and Echallier, JF. (1989).\n        Spherical splines for scalp potential and current density mapping.\n        Electroencephalography Clinical Neurophysiology, Feb; 72(2):184-7.\n    \"\"\"\n    pos_from = pos_from.copy()\n    pos_to = pos_to.copy()\n\n    # normalize sensor positions to sphere\n    _normalize_vectors(pos_from)\n    _normalize_vectors(pos_to)\n\n    # cosine angles between source positions\n    cosang_from = pos_from.dot(pos_from.T)\n    cosang_to_from = pos_to.dot(pos_from.T)\n    G_from = _calc_g(cosang_from)\n    G_to_from = _calc_g(cosang_to_from)\n\n    if alpha is not None:\n        G_from.flat[::len(G_from) + 1] += alpha\n\n    n_channels = G_from.shape[0]  # G_from should be square matrix\n    C = np.r_[np.c_[G_from, np.ones((n_channels, 1))],\n              np.c_[np.ones((1, n_channels)), 0]]\n    C_inv = linalg.pinv(C)\n\n    interpolation = np.c_[G_to_from,\n                          np.ones((G_to_from.shape[0], 1))].dot(C_inv[:, :-1])\n    return interpolation\n\n\ndef _do_interp_dots(inst, interpolation, goods_idx, bads_idx):\n    \"\"\"Dot product of channel mapping matrix to channel data.\"\"\"\n    from ..io.base import BaseRaw\n    from ..epochs import BaseEpochs\n    from ..evoked import Evoked\n\n    if isinstance(inst, (BaseRaw, Evoked)):\n        inst._data[bads_idx] = interpolation.dot(inst._data[goods_idx])\n    elif isinstance(inst, BaseEpochs):\n        inst._data[:, bads_idx, :] = einsum(\n            'ij,xjy->xiy', interpolation, inst._data[:, goods_idx, :])\n    else:\n        raise ValueError('Inputs of type {0} are not supported'\n                         .format(type(inst)))\n\n\n@verbose\ndef _interpolate_bads_eeg(inst, verbose=None):\n    \"\"\"Interpolate bad EEG channels.\n\n    Operates in place.\n\n    Parameters\n    ----------\n    inst : mne.io.Raw, mne.Epochs or mne.Evoked\n        The data to interpolate. Must be preloaded.\n    \"\"\"\n    bads_idx = np.zeros(len(inst.ch_names), dtype=np.bool)\n    goods_idx = np.zeros(len(inst.ch_names), dtype=np.bool)\n\n    picks = pick_types(inst.info, meg=False, eeg=True, exclude=[])\n    inst.info._check_consistency()\n    bads_idx[picks] = [inst.ch_names[ch] in inst.info['bads'] for ch in picks]\n\n    if len(picks) == 0 or bads_idx.sum() == 0:\n        return\n\n    goods_idx[picks] = True\n    goods_idx[bads_idx] = False\n\n    pos = inst._get_channel_positions(picks)\n\n    # Make sure only EEG are used\n    bads_idx_pos = bads_idx[picks]\n    goods_idx_pos = goods_idx[picks]\n\n    pos_good = pos[goods_idx_pos]\n    pos_bad = pos[bads_idx_pos]\n\n    # test spherical fit\n    radius, center = _fit_sphere(pos_good)\n    distance = np.sqrt(np.sum((pos_good - center) ** 2, 1))\n    distance = np.mean(distance / radius)\n    if np.abs(1. - distance) > 0.1:\n        warn('Your spherical fit is poor, interpolation results are '\n             'likely to be inaccurate.')\n\n    logger.info('Computing interpolation matrix from {0} sensor '\n                'positions'.format(len(pos_good)))\n\n    interpolation = _make_interpolation_matrix(pos_good, pos_bad)\n\n    logger.info('Interpolating {0} sensors'.format(len(pos_bad)))\n    _do_interp_dots(inst, interpolation, goods_idx, bads_idx)\n\n\n@verbose\ndef _interpolate_bads_meg(inst, mode='accurate', verbose=None):\n    \"\"\"Interpolate bad channels from data in good channels.\n\n    Parameters\n    ----------\n    inst : mne.io.Raw, mne.Epochs or mne.Evoked\n        The data to interpolate. Must be preloaded.\n    mode : str\n        Either `'accurate'` or `'fast'`, determines the quality of the\n        Legendre polynomial expansion used for interpolation. `'fast'` should\n        be sufficient for most applications.\n    verbose : bool, str, int, or None\n        If not None, override default verbose level (see :func:`mne.verbose`\n        and :ref:`Logging documentation <tut_logging>` for more).\n    \"\"\"\n    picks_meg = pick_types(inst.info, meg=True, eeg=False,\n                           ref_meg=True, exclude=[])\n    picks_good = pick_types(inst.info, meg=True, eeg=False,\n                            ref_meg=True, exclude='bads')\n    meg_ch_names = [inst.info['ch_names'][p] for p in picks_meg]\n    bads_meg = [ch for ch in inst.info['bads'] if ch in meg_ch_names]\n\n    # select the bad meg channel to be interpolated\n    if len(bads_meg) == 0:\n        picks_bad = []\n    else:\n        picks_bad = pick_channels(inst.info['ch_names'], bads_meg,\n                                  exclude=[])\n\n    # return without doing anything if there are no meg channels\n    if len(picks_meg) == 0 or len(picks_bad) == 0:\n        return\n    inst_info = inst.info.copy()\n    inst_info['comps'] = []\n    info_from = pick_info(inst_info, picks_good)\n    info_to = pick_info(inst_info, picks_bad)\n    mapping = _map_meg_channels(info_from, info_to, mode=mode)\n    _do_interp_dots(inst, mapping, picks_good, picks_bad)\n", "path": "mne/channels/interpolation.py"}]}