diff --git a/doc/changes/latest.inc b/doc/changes/latest.inc index 6e674cfe646..ed0b8ea27a4 100644 --- a/doc/changes/latest.inc +++ b/doc/changes/latest.inc @@ -47,6 +47,8 @@ Bugs - Fix reading of fiducial locations in :func:`mne.io.read_raw_eeglab` (:gh:`10521` by `Alex Gramfort`_) +- Prevent creation of montage with invalid ``[x, y, z]`` coordinates with :func:`mne.channels.make_dig_montage` (:gh:`10547` by `Mathieu Scheltienne`_) + API and behavior changes ~~~~~~~~~~~~~~~~~~~~~~~~ - When creating BEM surfaces via :func:`mne.bem.make_watershed_bem` and :func:`mne.bem.make_flash_bem`, the ``copy`` parameter now defaults to ``True``. This means that instead of creating symbolic links inside the FreeSurfer subject's ``bem`` folder, we now create "actual" files. This should avoid troubles when sharing files across different operating systems and file systems (:gh:`10531` by `Richard Höchenberger`_) diff --git a/mne/channels/tests/test_montage.py b/mne/channels/tests/test_montage.py index fd6dad3a695..3f3840a4348 100644 --- a/mne/channels/tests/test_montage.py +++ b/mne/channels/tests/test_montage.py @@ -1654,3 +1654,12 @@ def test_read_dig_localite(tmp_path): s = '' assert repr(montage) == s assert montage.ch_names == [f'ch{i:02}' for i in range(1, 16)] + + +def test_make_wrong_dig_montage(): + """Test that a montage with non numeric is not possible.""" + make_dig_montage(ch_pos={'A1': ['0', '0', '0']}) # converted to floats + with pytest.raises(ValueError, match="could not convert string to float"): + make_dig_montage(ch_pos={'A1': ['a', 'b', 'c']}) + with pytest.raises(TypeError, match="instance of ndarray, list, or tuple"): + make_dig_montage(ch_pos={'A1': 5}) diff --git a/mne/decoding/base.py b/mne/decoding/base.py index c0451723e39..85331da0ac7 100644 --- a/mne/decoding/base.py +++ b/mne/decoding/base.py @@ -382,7 +382,7 @@ def cross_val_multiscore(estimator, X, y=None, groups=None, scoring=None, Determines the cross-validation splitting strategy. Possible inputs for cv are: - - None, to use the default 3-fold cross validation, + - None, to use the default 5-fold cross validation, - integer, to specify the number of folds in a ``(Stratified)KFold``, - An object to be used as a cross-validation generator. - An iterable yielding train, test splits. diff --git a/mne/io/_digitization.py b/mne/io/_digitization.py index 67e44716c94..f0aaada8a67 100644 --- a/mne/io/_digitization.py +++ b/mne/io/_digitization.py @@ -425,12 +425,22 @@ def _make_dig_points(nasion=None, lpa=None, rpa=None, hpi=None, 'kind': FIFF.FIFFV_POINT_EXTRA, 'coord_frame': coord_frame}) if dig_ch_pos is not None: - try: # use the last 3 as int if possible (e.g., EEG001->1) - idents = [] - for key in dig_ch_pos: - _validate_type(key, str, 'dig_ch_pos') + idents = [] + use_arange = False + for key, value in dig_ch_pos.items(): + _validate_type(key, str, 'dig_ch_pos') + try: idents.append(int(key[-3:])) - except ValueError: # and if any conversion fails, simply use arange + except ValueError: + use_arange = True + _validate_type(value, (np.ndarray, list, tuple), 'dig_ch_pos') + value = np.array(value, dtype=float) + dig_ch_pos[key] = value + if value.shape != (3, ): + raise RuntimeError( + "The position should be a 1D array of 3 floats. " + f"Provided shape {value.shape}.") + if use_arange: idents = np.arange(1, len(dig_ch_pos) + 1) for key, ident in zip(dig_ch_pos, idents): dig.append({'r': dig_ch_pos[key], 'ident': int(ident),