Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into cola5
Browse files Browse the repository at this point in the history
* upstream/main: (26 commits)
  MAINT: Better fix for deprecation (mne-tools#11789)
  udpate doc for 11786 (mne-tools#11787)
  MAINT: Ignore warning in example (mne-tools#11781)
  Keeping event names when combining channel on epochs objects (mne-tools#11786)
  DOC: Fix incorrect docs for annotate_movement [ci skip] (mne-tools#11779)
  Refresh eegbci code and docstrings (mne-tools#11783)
  DOC: EEG eye-tracking alignment tutorial (mne-tools#11770)
  [MRG] By-pass set_annotations when plotting ICA sources  (mne-tools#11766)
  add missing changelog from 11773 (mne-tools#11777)
  Fix eeglab.py, an error for read annotations in `RawEEGLab` (mne-tools#11773)
  [MRG] Use FIFF.FIFF_UNITM_NONE instead of 0 when adding a reference channel (mne-tools#11774)
  MAINT: Update for linkcheck [circle linkcheck] (mne-tools#11771)
  ENH: Interpolate blinks in eyetrack channels (mne-tools#11740)
  MAINT: Work around joblib bug (mne-tools#11765)
  Update manual install docs (mne-tools#11764)
  add logging message about which EOG channel used for blink detection (mne-tools#11757)
  DOC: Fix docs (mne-tools#11756)
  BUG: Fix bug with SNR calculation (mne-tools#11755)
  BUG: Fix bug with cHPI off (mne-tools#11754)
  Change color from annotation to red if name changes to "bad_" or "edge_" (mne-tools#11753)
  ...
  • Loading branch information
larsoner committed Jul 10, 2023
2 parents 57701e5 + e289436 commit 2725a52
Show file tree
Hide file tree
Showing 62 changed files with 1,146 additions and 628 deletions.
2 changes: 1 addition & 1 deletion doc/changes/1.1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Enhancements

- Add ``head_source`` argument to :func:`mne.make_field_map` to allow selecting which head source to use (:gh:`10568` by `Eric Larson`_)

- Add support for ``n_jobs=None`` to support :func:`joblib:joblib.parallel_backend` for more precise control over parallelization (:gh:`10567` by `Eric Larson`_)
- Add support for ``n_jobs=None`` to support ``joblib:joblib.parallel_backend`` for more precise control over parallelization (:gh:`10567` by `Eric Larson`_)

- It is now possible to compute inverse solutions with restricted source orientations using discrete forward models (:gh:`10464` by `Marijn van Vliet`_)

Expand Down
11 changes: 11 additions & 0 deletions doc/changes/latest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ Current (1.5.dev0)
Enhancements
~~~~~~~~~~~~
- Add ``cmap`` argument for the :func:`mne.viz.plot_sensors` (:gh:`11720` by :newcontrib:`Gennadiy Belonosov`)
- Return unmodified instance if new sampling frequency is identical to the original in :meth:`mne.io.Raw.resample`, :meth:`mne.Epochs.resample`, :meth:`mne.Evoked.resample` and :meth:`mne.SourceEstimate.resample` (:gh:`11736` by :newcontrib:`Gennadiy Belonosov`)
- When failing to locate a file, we now print the full path in quotation marks to help spot accidentally added trailing spaces (:gh:`11718` by `Richard Höchenberger`_)
- Add standard montage lookup table for ``easycap-M43`` (:gh:`11744` by :newcontrib:`Diptyajit Das`)
- Added :class:`mne.preprocessing.eyetracking.Calibration` to store eye-tracking calibration info, and :func:`mne.preprocessing.eyetracking.read_eyelink_calibration` to read calibration data from EyeLink systems (:gh:`11719` by `Scott Huberty`_)
- Ocular :class:`mne.Annotations` read in by :func:`mne.io.read_raw_eyelink` are now channel aware. This means if the left eye blinked, the associated annotation will store this in the ``'ch_names'`` key. (:gh:`11746` by `Scott Huberty`_)
- Added :func:`mne.preprocessing.eyetracking.interpolate_blinks` to linear interpolate eyetrack signals during blink periods. (:gh:`11740` by `Scott Huberty`_)
- Added a section for combining eye-tracking and EEG data to the preprocessing tutorial "working with eye tracker data in MNE-Python" (:gh:`11770` by `Scott Huberty`_)

Bugs
~~~~
- Fix bug where epochs ``event_id`` was not kept by :func:`mne.channels.combine_channels` (:gh:`11786` by :newcontrib:`Samuel Louviot`)
- Fix bug where user-provided codec was not used to read annotations when loading EEGLAB ``.set`` files (:gh:`11773` by :newcontrib:`Yiping Zuo`)
- Fix bug that required curv.*h files to create Brain object (:gh:`11704` by :newcontrib:`Aaron Earle-Richardson`)
- Extended test to highlight bug in :func:`mne.stats.permutation_t_test` (:gh:`11575` by :newcontrib:`Joshua Calder-Travis`)
- Fix bug where :meth:`mne.viz.Brain.add_volume_labels` used an incorrect orientation (:gh:`11730` by `Alex Rockhill`_)
Expand All @@ -38,9 +44,14 @@ Bugs
- Fix hanging interpreter with matplotlib figures using ``mne/viz/_mpl_figure.py`` in spyder console and jupyter notebooks (:gh:`11696` by `Mathieu Scheltienne`_)
- Fix bug with overlapping text for :meth:`mne.Evoked.plot` (:gh:`11698` by `Alex Rockhill`_)
- For :func:`mne.io.read_raw_eyelink`, the default value of the ``gap_description`` parameter is now ``'BAD_ACQ_SKIP'``, following MNE convention (:gh:`11719` by `Scott Huberty`_)
- Fix bug with :func:`mne.io.read_raw_fil` where datasets without sensor positions would not import (:gh:`11733` by `George O'Neill`_)
- Fix bug with :func:`mne.chpi.compute_chpi_snr` where cHPI being off for part of the recording or bad channels being defined led to an error or incorrect behavior (:gh:`11754`, :gh:`11755` by `Eric Larson`_)
- Allow int-like for the argument ``id`` of `~mne.make_fixed_length_events` (:gh:`11748` by `Mathieu Scheltienne`_)
- blink :class:`mne.Annotations` read in by :func:`mne.io.read_raw_eyelink` now begin with ``'BAD_'``, i.e. ``'BAD_blink'``, because ocular data are missing during blinks. (:gh:`11746` by `Scott Huberty`_)
- Fix display of :class:`~mne.Annotations` in `mne.preprocessing.ICA.plot_sources` when the ``raw`` has ``raw.first_samp != 0`` and doesn't have a measurement date (:gh:`11766` by `Mathieu Scheltienne`_)
API changes
~~~~~~~~~~~
- The ``baseline`` argument can now be array-like (e.g. ``list``, ``tuple``, ``np.ndarray``, ...) instead of only a ``tuple`` (:gh:`11713` by `Clemens Brunner`_)
- The ``events`` and ``event_id`` parameters of `:meth:`Epochs.plot() <mne.Epochs.plot>` now accept boolean values; see docstring for details (:gh:`11445` by `Daniel McCloy`_ and `Clemens Brunner`_)
- Deprecated ``gap_description`` keyword argument of :func:`mne.io.read_raw_eyelink`, which will be removed in mne version 1.6, in favor of using :meth:`mne.Annotations.rename` (:gh:`11719` by `Scott Huberty`_)
4 changes: 4 additions & 0 deletions doc/changes/names.inc
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@

.. _Samuel Deslauriers-Gauthier: https://github.com/sdeslauriers

.. _Samuel Louviot: https://github.com/Sam54000

.. _Samuel Powell: https://github.com/samuelpowell

.. _Santeri Ruuskanen: https://github.com/ruuskas
Expand Down Expand Up @@ -554,6 +556,8 @@

.. _Yaroslav Halchenko: http://haxbylab.dartmouth.edu/ppl/yarik.html

.. _Yiping Zuo: https://github.com/frostime

.. _Yousra Bekhti: https://www.linkedin.com/pub/yousra-bekhti/56/886/421

.. _Yu-Han Luo: https://github.com/yh-luo
Expand Down
11 changes: 10 additions & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ def append_attr_meth_examples(app, what, name, obj, options, lines):
"https://doi.org/10.1167/", # jov.arvojournals.org
"https://doi.org/10.1177/", # journals.sagepub.com
"https://doi.org/10.1063/", # pubs.aip.org/aip/jap
"https://doi.org/10.1080/", # www.tandfonline.com
"https://doi.org/10.1088/", # www.tandfonline.com
"https://doi.org/10.3109/", # www.tandfonline.com
"https://www.researchgate.net/profile/",
# 503 Server error
"https://hal.archives-ouvertes.fr/hal-01848442",
Expand Down Expand Up @@ -1290,7 +1293,13 @@ def reset_warnings(gallery_conf, fname):
)
warnings.filterwarnings(
"ignore",
message=("Matplotlib is currently using agg, which is a non-GUI backend.*"),
message="Matplotlib is currently using agg, which is a non-GUI backend.*",
)
# seaborn
warnings.filterwarnings(
"ignore",
message="The figure layout has changed to tight",
category=UserWarning,
)
# matplotlib 3.6 in nilearn and pyvista
warnings.filterwarnings("ignore", message=".*cmap function will be deprecated.*")
Expand Down
46 changes: 28 additions & 18 deletions doc/install/manual_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ Install via :code:`pip` or :code:`conda`
instead.

MNE-Python requires Python version |min_python_version| or higher. If you
need to install Python, please see :ref:`install-python`.
need help installing Python, please refer to our :ref:`install-python` guide.

Installing MNE-Python with all dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We suggest to install MNE-Python into its own ``conda`` environment.
If you use Anaconda, we suggest installing MNE-Python into its own ``conda`` environment.

The dependency stack is large and may take a long time (several tens of
minutes) to resolve on some systems via the default ``conda`` solver. We
minutes) to resolve on some systems via the default ``conda`` command. We
therefore highly recommend using `mamba <https://mamba.readthedocs.io/>`__
instead, a ``conda`` replacement that is **much** faster.

Expand All @@ -35,12 +35,12 @@ dependencies into it.

If you need to convert structural MRI scans into models
of the scalp, inner/outer skull, and cortical surfaces, you will also need
:doc:`FreeSurfer <freesurfer>`.
to install :doc:`FreeSurfer <freesurfer>`.

Installing a minimal MNE-Python with core functionality only
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you only need MNE-Python's core functionality including 2D plotting (but
**without 3D visualization**), install via :code:`pip`:
Installing MNE-Python with core dependencies
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you only need MNE-Python's core functionality, which includes 2D plotting
(but does not support 3D visualization), install via :code:`pip`:

.. code-block:: console
Expand All @@ -55,17 +55,21 @@ or via :code:`conda`:
This will create a new ``conda`` environment called ``mne`` (you can adjust
this by passing a different name via ``--name``).

Installing a minimal MNE-Python with EEGLAB I/O support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you plan to use MNE-Python's functions that require **HDF5 I/O** (this
This minimal installation requires only a few dependencies. If you need additional
functionality later on, you can install individual packages as needed.

Installing MNE-Python with HDF5 support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
If you plan to use MNE-Python's functions that require
`HDF5 <https://www.hdfgroup.org/solutions/hdf5/>`__ I/O (this
includes :func:`mne.io.read_raw_eeglab`, :meth:`mne.SourceMorph.save`, and
others), you should run via :code:`pip`:

.. code-block:: console
$ pip install mne[hdf5]
or via :code:`conda`
or via :code:`conda`:

.. code-block:: console
Expand All @@ -74,6 +78,13 @@ or via :code:`conda`
This will create a new ``conda`` environment called ``mne`` (you can adjust
this by passing a different name via ``--name``).

If you have already installed MNE-Python with core dependencies (e.g. via ``pip install mne``),
you can install these two packages to unlock HDF5 support:

.. code-block:: console
$ pip install h5io pymatreader
Installing MNE-Python for other scenarios
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The :ref:`advanced_setup` page has additional
Expand All @@ -92,7 +103,7 @@ Python development are:
- `Visual Studio Code`_ (often shortened to "VS Code" or "vscode") is a
development-focused text editor that supports many programming languages in
addition to Python, includes an integrated terminal console, and has a rich
ecosystem of packages to extend its capabilities. Installing
extension ecosystem. Installing
`Microsoft's Python Extension
<https://marketplace.visualstudio.com/items?itemName=ms-python.python>`__ is
enough to get most Python users up and running. VS Code is free and
Expand All @@ -103,11 +114,11 @@ Python development are:
``spyder`` (or on Windows or macOS, launched from the Anaconda Navigator GUI).
It can also be installed with `dedicated installers <https://www.spyder-ide.org/#section-download>`_.
To avoid dependency conflicts with Spyder, you should install ``mne`` in a
separate environment, like explained in the earlier sections. Then, set
separate environment, as explained in previous sections. Then, instruct
Spyder to use the ``mne`` environment as its default interpreter by opening
Spyder and navigating to
:samp:`Tools > Preferences > Python Interpreter > Use the following interpreter`.
There, paste the output of the following terminal commands
There, paste the output of the following terminal commands:

.. code-block:: console
Expand Down Expand Up @@ -135,6 +146,5 @@ Python development are:
environment.

- `PyCharm`_ is an IDE specifically for Python development that provides an
all-in-one installation (no extension packages needed). PyCharm comes in a
free "community" edition and a paid "professional" edition, and is
closed-source.
all-in-one solution (no extension packages needed). PyCharm comes in a
free and open-source Community edition as well as a paid Professional edition.
11 changes: 7 additions & 4 deletions doc/overview/datasets_index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -475,14 +475,17 @@ standard.

* :ref:`tut-ssvep`

.. _eyelink-dataset:

EYELINK
=======
:func:`mne.datasets.eyelink.data_path`

A small example dataset in SR research's proprietary .asc format.
1 participant fixated on the screen while short light flashes appeared.
Monocular recording of gaze position and pupil size, 1000 Hz sampling
frequency.
A small example dataset from a pupillary light reflex experiment. Both EEG (EGI) and
eye-tracking (SR Research EyeLink; ASCII format) data were recorded and stored in
separate files. 1 participant fixated on the screen while short light flashes appeared.
Event onsets were recorded by a photodiode attached to the screen and were
sent to both the EEG and eye-tracking systems.

.. topic:: Examples

Expand Down
1 change: 1 addition & 0 deletions doc/preprocessing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ Projections:
Calibration
read_eyelink_calibration
set_channel_types_eyetrack
interpolate_blinks

EEG referencing:

Expand Down
1 change: 0 additions & 1 deletion examples/time_frequency/time_frequency_erds.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@
from mne.time_frequency import tfr_multitaper
from mne.stats import permutation_cluster_1samp_test as pcluster_test


# %%
# First, we load and preprocess the data. We use runs 6, 10, and 14 from
# subject 1 (these runs contains hand and feet motor imagery).
Expand Down
5 changes: 4 additions & 1 deletion mne/channels/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
_on_missing,
legacy,
)
from ..io.constants import FIFF
from ..io.constants import FIFF, _ch_unit_mul_named
from ..io.meas_info import (
anonymize_info,
Info,
Expand Down Expand Up @@ -442,6 +442,8 @@ def set_channel_types(self, mapping, *, on_unit_change="warn", verbose=None):
if this_change not in unit_changes:
unit_changes[this_change] = list()
unit_changes[this_change].append(ch_name)
# reset unit multiplication factor since the unit has now changed
self.info["chs"][c_ind]["unit_mul"] = _ch_unit_mul_named[0]
self.info["chs"][c_ind]["unit"] = _human2unit[ch_type]
if ch_type in ["eeg", "seeg", "ecog", "dbs"]:
coil_type = FIFF.FIFFV_COIL_EEG
Expand Down Expand Up @@ -2298,6 +2300,7 @@ def combine_channels(
new_data,
info,
events=inst.events,
event_id=inst.event_id,
tmin=inst.times[0],
baseline=inst.baseline,
)
Expand Down
9 changes: 8 additions & 1 deletion mne/channels/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
read_raw_kit,
RawArray,
)
from mne.io.constants import FIFF
from mne.io.constants import FIFF, _ch_unit_mul_named
from mne import (
pick_types,
pick_channels,
Expand Down Expand Up @@ -223,6 +223,13 @@ def test_set_channel_types():
ch_types = {raw.ch_names[0]: "misc"}
pytest.raises(ValueError, raw.set_channel_types, ch_types)

# test reset of channel units on unit change
idx = raw.ch_names.index("EEG 003")
raw.info["chs"][idx]["unit_mul"] = _ch_unit_mul_named[-6]
assert raw.info["chs"][idx]["unit_mul"] == -6
raw.set_channel_types({"EEG 003": "misc"}, on_unit_change="ignore")
assert raw.info["chs"][idx]["unit_mul"] == 0


def test_get_builtin_ch_adjacencies():
"""Test retrieving the names of all built-in FieldTrip neighbors."""
Expand Down
16 changes: 10 additions & 6 deletions mne/chpi.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,15 @@ def _setup_hpi_amplitude_fitting(
inv_model_reord = _reorder_inv_model(inv_model, len(hpi_freqs))
proj, proj_op, meg_picks = _setup_ext_proj(info, ext_order)
# include mag and grad picks separately, for SNR computations
mag_picks = _picks_to_idx(info, "mag", allow_empty=True)
grad_picks = _picks_to_idx(info, "grad", allow_empty=True)
mag_subpicks = _picks_to_idx(info, "mag", allow_empty=True)
mag_subpicks = np.searchsorted(meg_picks, mag_subpicks)
grad_subpicks = _picks_to_idx(info, "grad", allow_empty=True)
grad_subpicks = np.searchsorted(meg_picks, grad_subpicks)
# Set up magnetic dipole fits
hpi = dict(
meg_picks=meg_picks,
mag_picks=mag_picks,
grad_picks=grad_picks,
mag_subpicks=mag_subpicks,
grad_subpicks=grad_subpicks,
hpi_pick=hpi_pick,
model=model,
inv_model=inv_model,
Expand Down Expand Up @@ -779,8 +781,8 @@ def _fit_chpi_amplitudes(raw, time_sl, hpi, snr=False):
len(hpi["freqs"]),
hpi["model"],
hpi["inv_model"],
hpi["mag_picks"],
hpi["grad_picks"],
hpi["mag_subpicks"],
hpi["grad_subpicks"],
)
return _fast_fit(
this_data,
Expand Down Expand Up @@ -1245,6 +1247,8 @@ def _compute_chpi_amp_or_snr(
#
amps_or_snrs = _fit_chpi_amplitudes(raw, time_sl, hpi, snr)
if snr:
if amps_or_snrs is None:
amps_or_snrs = np.full((n_freqs, grad_offset + 3), np.nan)
# unpack the SNR estimates. mag & grad are returned in one array
# (because of Numba) so take care with which column is which.
# note that mean residual is a scalar (same for all HPI freqs) but
Expand Down
2 changes: 2 additions & 0 deletions mne/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ def pytest_configure(config):
ignore:`product` is deprecated as of NumPy.*:DeprecationWarning
# pandas
ignore:.*np\.find_common_type is deprecated.*:DeprecationWarning
# https://github.com/joblib/joblib/issues/1454
ignore:.*`byte_bounds` is dep.*:DeprecationWarning
""" # noqa: E501
for warning_line in warning_lines.split("\n"):
warning_line = warning_line.strip()
Expand Down
6 changes: 3 additions & 3 deletions mne/datasets/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,9 @@

# eyelink dataset
MNE_DATASETS["eyelink"] = dict(
archive_name="eyelink_example_data.zip",
hash="md5:081950c05f35267458d9c751e178f161",
url=("https://osf.io/r5ndq/download?version=1"),
archive_name="eeg-eyetrack_data.zip",
hash="md5:c4fc788fe01737e08e9086c90cab642d",
url=("https://osf.io/63fjm/download?version=1"),
folder_name="eyelink-example-data",
config_key="MNE_DATASETS_EYELINK_PATH",
)
Loading

0 comments on commit 2725a52

Please sign in to comment.