Skip to content

Commit 174c540

Browse files
Mettphysikpre-commit-ci[bot]larsonerPaul Anders
authored
Changing the default value of "origin" for future versions in make_field_map and other methods (#13398)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Larson <[email protected]> Co-authored-by: Paul Anders <[email protected]>
1 parent a8e2fe8 commit 174c540

File tree

14 files changed

+81
-30
lines changed

14 files changed

+81
-30
lines changed

.github/workflows/tests.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ jobs:
130130
sed -i "/numba/d" environment.yml
131131
# And on Windows and macOS PySide6.9.0 segfaults
132132
elif [[ "$RUNNER_OS" == "macOS" ]]; then
133-
sed -i "" "s/ - PySide6 .*/ - PySide6 <6.8/g" environment.yml
133+
sed -i "" "s/ - PySide6 .*/ - PySide6 =6.7.3/g" environment.yml
134+
sed -i "" "s/ - vtk .*/ - vtk =9.3.1/g" environment.yml
134135
elif [[ "$RUNNER_OS" == "Windows" ]]; then
135136
sed -i "s/ - PySide6 .*/ - PySide6 <6.8/g" environment.yml
136137
fi
@@ -139,8 +140,10 @@ jobs:
139140
with:
140141
environment-file: ${{ env.CONDA_ENV }}
141142
environment-name: mne
143+
log-level: ${{ runner.debug == '1' && 'debug' || 'info' }}
142144
create-args: >-
143145
python=${{ env.PYTHON_VERSION }}
146+
-v
144147
if: ${{ !startswith(matrix.kind, 'pip') }}
145148
timeout-minutes: 20
146149
- run: bash ./tools/github_actions_dependencies.sh
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The default for :func:`mne.make_field_map` will change to ``"auto"`` in MNE-Python 1.12 (from ``(0., 0., 0.04)``), changes by :newcontrib:`Paul Anders`.

doc/changes/names.inc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@
231231
.. _Pablo Mainar: https://github.com/pablomainar
232232
.. _Pablo-Arias: https://github.com/Pablo-Arias
233233
.. _Padma Sundaram: https://www.nmr.mgh.harvard.edu/user/8071
234+
.. _Paul Anders: https://github.com/Mettphysik
234235
.. _Paul Pasler: https://github.com/ppasler
235236
.. _Paul Roujansky: https://github.com/paulroujansky
236237
.. _Pavel Navratil: https://github.com/navrpa13

examples/visualization/mne_helmet.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
subject="sample",
3737
subjects_dir=subjects_dir,
3838
upsampling=2,
39+
origin="auto",
3940
)
4041
time = 0.083
4142
fig = mne.viz.create_3d_figure((512, 512), bgcolor="w", title="MNE helmet")

mne/channels/channels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,7 @@ def interpolate_bads(
934934
origin = _check_origin(origin, self.info)
935935
for ch_type, interp in method.items():
936936
if interp == "nan":
937-
_interpolate_bads_nan(self, ch_type, exclude=exclude)
937+
_interpolate_bads_nan(self, ch_type=ch_type, exclude=exclude)
938938
if method.get("eeg", "") == "spline":
939939
_interpolate_bads_eeg(self, origin=origin, exclude=exclude)
940940
meg_mne = method.get("meg", "") == "MNE"

mne/channels/interpolation.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,25 +172,25 @@ def _interpolate_bads_eeg(inst, origin, exclude=None, ecog=False, verbose=None):
172172

173173

174174
@verbose
175-
def _interpolate_bads_ecog(inst, origin, exclude=None, verbose=None):
175+
def _interpolate_bads_ecog(inst, *, origin, exclude=None, verbose=None):
176176
_interpolate_bads_eeg(inst, origin, exclude=exclude, ecog=True, verbose=verbose)
177177

178178

179179
def _interpolate_bads_meg(
180-
inst, mode="accurate", origin=(0.0, 0.0, 0.04), verbose=None, ref_meg=False
180+
inst, mode="accurate", *, origin, verbose=None, ref_meg=False
181181
):
182182
return _interpolate_bads_meeg(
183-
inst, mode, origin, ref_meg=ref_meg, eeg=False, verbose=verbose
183+
inst, mode, ref_meg=ref_meg, eeg=False, origin=origin, verbose=verbose
184184
)
185185

186186

187187
@verbose
188188
def _interpolate_bads_nan(
189189
inst,
190+
*,
190191
ch_type,
191192
ref_meg=False,
192193
exclude=(),
193-
*,
194194
verbose=None,
195195
):
196196
info = _simplify_info(inst.info)
@@ -208,12 +208,12 @@ def _interpolate_bads_nan(
208208
def _interpolate_bads_meeg(
209209
inst,
210210
mode="accurate",
211-
origin=(0.0, 0.0, 0.04),
211+
*,
212212
meg=True,
213213
eeg=True,
214214
ref_meg=False,
215215
exclude=(),
216-
*,
216+
origin,
217217
method=None,
218218
verbose=None,
219219
):

mne/channels/tests/test_interpolation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ def test_interpolation_meg():
264264
def _this_interpol(inst, ref_meg=False):
265265
from mne.channels.interpolation import _interpolate_bads_meg
266266

267-
_interpolate_bads_meg(inst, ref_meg=ref_meg, mode="fast")
267+
_interpolate_bads_meg(inst, ref_meg=ref_meg, mode="fast", origin=(0.0, 0.0, 0.04))
268268
return inst
269269

270270

mne/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,7 @@ def _check_skip_backend(name):
672672
assert name == "notebook", name
673673
pytest.importorskip("jupyter")
674674
pytest.importorskip("ipympl")
675+
pytest.importorskip("ipyevents")
675676
pytest.importorskip("trame")
676677
pytest.importorskip("trame_vtk")
677678
pytest.importorskip("trame_vuetify")

mne/forward/_field_interpolation.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from ..fixes import _safe_svd
2323
from ..surface import get_head_surf, get_meg_helmet_surf
2424
from ..transforms import _find_trans, transform_surface_to
25-
from ..utils import _check_fname, _check_option, _pl, _reg_pinv, logger, verbose
25+
from ..utils import _check_fname, _check_option, _pl, _reg_pinv, logger, verbose, warn
2626
from ._lead_dots import (
2727
_do_cross_dots,
2828
_do_self_dots,
@@ -116,7 +116,7 @@ def _pinv_tikhonov(x, reg):
116116
return inv, n
117117

118118

119-
def _map_meg_or_eeg_channels(info_from, info_to, mode, origin, miss=None):
119+
def _map_meg_or_eeg_channels(info_from, info_to, mode, *, origin, miss=None):
120120
"""Find mapping from one set of channels to another.
121121
122122
Parameters
@@ -132,13 +132,15 @@ def _map_meg_or_eeg_channels(info_from, info_to, mode, origin, miss=None):
132132
origin : array-like, shape (3,) | str
133133
Origin of the sphere in the head coordinate frame and in meters.
134134
Can be ``'auto'``, which means a head-digitization-based origin
135-
fit. Default is ``(0., 0., 0.04)``.
135+
fit.
136136
137137
Returns
138138
-------
139139
mapping : array, shape (n_to, n_from)
140140
A mapping matrix.
141141
"""
142+
assert origin is not None # should be assured elsewhere
143+
142144
# no need to apply trans because both from and to coils are in device
143145
# coordinates
144146
info_kinds = set(ch["kind"] for ch in info_to["chs"])
@@ -314,7 +316,8 @@ def _make_surface_mapping(
314316
trans=None,
315317
mode="fast",
316318
n_jobs=None,
317-
origin=(0.0, 0.0, 0.04),
319+
*,
320+
origin,
318321
verbose=None,
319322
):
320323
"""Re-map M/EEG data to a surface.
@@ -337,8 +340,6 @@ def _make_surface_mapping(
337340
%(n_jobs)s
338341
origin : array-like, shape (3,) | str
339342
Origin of the sphere in the head coordinate frame and in meters.
340-
The default is ``'auto'``, which means a head-digitization-based
341-
origin fit.
342343
%(verbose)s
343344
344345
Returns
@@ -347,6 +348,8 @@ def _make_surface_mapping(
347348
A n_vertices x n_sensors array that remaps the MEG or EEG data,
348349
as `new_data = np.dot(mapping, data)`.
349350
"""
351+
assert origin is not None # should be assured elsewhere
352+
350353
if not all(key in surf for key in ["rr", "nn"]):
351354
raise KeyError('surf must have both "rr" and "nn"')
352355
if "coord_frame" not in surf:
@@ -443,7 +446,7 @@ def make_field_map(
443446
ch_type=None,
444447
mode="fast",
445448
meg_surf="helmet",
446-
origin=(0.0, 0.0, 0.04),
449+
origin=None,
447450
n_jobs=None,
448451
*,
449452
upsampling=1,
@@ -483,6 +486,9 @@ def make_field_map(
483486
fit. Default is ``(0., 0., 0.04)``.
484487
485488
.. versionadded:: 0.11
489+
.. versionchanged:: 1.12
490+
In 1.12 the default value is "auto".
491+
In 1.11 and prior versions, it is ``(0., 0., 0.04)``.
486492
%(n_jobs)s
487493
%(helmet_upsampling)s
488494
@@ -498,6 +504,15 @@ def make_field_map(
498504
The surface maps to be used for field plots. The list contains
499505
separate ones for MEG and EEG (if both MEG and EEG are present).
500506
"""
507+
if origin is None:
508+
warn_message = (
509+
'Default value for origin is "(0.0, 0.0, 0.04)" in version 1.11 '
510+
'but will be changed to "auto" in 1.12. Set the origin parameter '
511+
"explicitly to avoid this warning."
512+
)
513+
warn(warn_message, FutureWarning)
514+
origin = (0.0, 0.0, 0.04)
515+
501516
info = evoked.info
502517

503518
if ch_type is None:

mne/forward/tests/test_field_interpolation.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@ def test_field_map_ctf():
5050
evoked = Epochs(raw, events).average()
5151
evoked.pick(evoked.ch_names[:50]) # crappy mapping but faster
5252
# smoke test - passing trans_fname as pathlib.Path as additional check
53+
# set origin to "(0.0, 0.0, 0.04)", which was the default until v1.12
54+
# estimating origin from "auto" impossible due to missing digitization points
5355
make_field_map(
54-
evoked, trans=Path(trans_fname), subject="sample", subjects_dir=subjects_dir
56+
evoked,
57+
trans=Path(trans_fname),
58+
subject="sample",
59+
subjects_dir=subjects_dir,
60+
origin=(0.0, 0.0, 0.04),
5561
)
5662

5763

@@ -128,11 +134,13 @@ def test_make_field_map_eeg():
128134
evoked.info["bads"] = ["MEG 2443", "EEG 053"] # add some bads
129135
surf = get_head_surf("sample", subjects_dir=subjects_dir)
130136
# we must have trans if surface is in MRI coords
131-
pytest.raises(ValueError, _make_surface_mapping, evoked.info, surf, "eeg")
137+
pytest.raises(
138+
ValueError, _make_surface_mapping, evoked.info, surf, "eeg", origin="auto"
139+
)
132140

133141
evoked.pick(picks="eeg")
134142
fmd = make_field_map(
135-
evoked, trans_fname, subject="sample", subjects_dir=subjects_dir
143+
evoked, trans_fname, subject="sample", subjects_dir=subjects_dir, origin="auto"
136144
)
137145

138146
# trans is necessary for EEG only
@@ -143,10 +151,11 @@ def test_make_field_map_eeg():
143151
None,
144152
subject="sample",
145153
subjects_dir=subjects_dir,
154+
origin="auto",
146155
)
147156

148157
fmd = make_field_map(
149-
evoked, trans_fname, subject="sample", subjects_dir=subjects_dir
158+
evoked, trans_fname, subject="sample", subjects_dir=subjects_dir, origin="auto"
150159
)
151160
assert len(fmd) == 1
152161
assert_array_equal(fmd[0]["data"].shape, (642, 59)) # maps data onto surf
@@ -163,31 +172,37 @@ def test_make_field_map_meg():
163172
# let's reduce the number of channels by a bunch to speed it up
164173
info["bads"] = info["ch_names"][:200]
165174
# bad ch_type
166-
pytest.raises(ValueError, _make_surface_mapping, info, surf, "foo")
175+
pytest.raises(ValueError, _make_surface_mapping, info, surf, "foo", origin="auto")
167176
# bad mode
168-
pytest.raises(ValueError, _make_surface_mapping, info, surf, "meg", mode="foo")
177+
pytest.raises(
178+
ValueError, _make_surface_mapping, info, surf, "meg", mode="foo", origin="auto"
179+
)
169180
# no picks
170181
evoked_eeg = evoked.copy().pick(picks="eeg")
171-
pytest.raises(RuntimeError, _make_surface_mapping, evoked_eeg.info, surf, "meg")
182+
pytest.raises(
183+
RuntimeError, _make_surface_mapping, evoked_eeg.info, surf, "meg", origin="auto"
184+
)
172185
# bad surface def
173186
nn = surf["nn"]
174187
del surf["nn"]
175-
pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg")
188+
pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg", origin="auto")
176189
surf["nn"] = nn
177190
cf = surf["coord_frame"]
178191
del surf["coord_frame"]
179-
pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg")
192+
pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg", origin="auto")
180193
surf["coord_frame"] = cf
181194

182195
# now do it with make_field_map
183196
evoked.pick(picks="meg")
184197
evoked.info.normalize_proj() # avoid projection warnings
185-
fmd = make_field_map(evoked, None, subject="sample", subjects_dir=subjects_dir)
198+
fmd = make_field_map(
199+
evoked, None, subject="sample", subjects_dir=subjects_dir, origin="auto"
200+
)
186201
assert len(fmd) == 1
187202
assert_array_equal(fmd[0]["data"].shape, (304, 106)) # maps data onto surf
188203
assert len(fmd[0]["ch_names"]) == 106
189204

190-
pytest.raises(ValueError, make_field_map, evoked, ch_type="foobar")
205+
pytest.raises(ValueError, make_field_map, evoked, ch_type="foobar", origin="auto")
191206

192207
# now test the make_field_map on head surf for MEG
193208
evoked.pick(picks="meg")
@@ -198,6 +213,7 @@ def test_make_field_map_meg():
198213
meg_surf="head",
199214
subject="sample",
200215
subjects_dir=subjects_dir,
216+
origin="auto",
201217
)
202218
assert len(fmd) == 1
203219
assert_array_equal(fmd[0]["data"].shape, (642, 106)) # maps data onto surf
@@ -210,6 +226,7 @@ def test_make_field_map_meg():
210226
meg_surf="foobar",
211227
subjects_dir=subjects_dir,
212228
trans=trans_fname,
229+
origin="auto",
213230
)
214231

215232

@@ -221,12 +238,15 @@ def test_make_field_map_meeg():
221238
picks = picks[::10]
222239
evoked.pick([evoked.ch_names[p] for p in picks])
223240
evoked.info.normalize_proj()
241+
# set origin to "(0.0, 0.0, 0.04)", which was the default until v1.12
242+
# estimated origin from "auto" fails the assertions below
224243
maps = make_field_map(
225244
evoked,
226245
trans_fname,
227246
subject="sample",
228247
subjects_dir=subjects_dir,
229248
verbose="debug",
249+
origin=(0.0, 0.0, 0.04),
230250
)
231251
assert_equal(maps[0]["data"].shape, (642, 6)) # EEG->Head
232252
assert_equal(maps[1]["data"].shape, (304, 31)) # MEG->Helmet

0 commit comments

Comments
 (0)