diff --git a/.github/workflows/credit.yml b/.github/workflows/credit.yml index e3fda39f7b2..1e4f9ff0931 100644 --- a/.github/workflows/credit.yml +++ b/.github/workflows/credit.yml @@ -38,8 +38,8 @@ jobs: git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions[bot]" git checkout -b credit - git commit -am "MAINT: Update code credit [ci skip]" + git commit -am "MAINT: Update code credit" git push origin credit - PR_NUM=$(gh pr create --base main --head credit --title "MAINT: Update code credit" --body "Created by credit GitHub action." --label "no-changelog-entry-needed") + PR_NUM=$(gh pr create --base main --head credit --title "MAINT: Update code credit" --body "Created by credit [GitHub action](https://github.com/mne-tools/mne-python/actions/runs/${{ github.run_id }})." --label "no-changelog-entry-needed") echo "Opened https://github.com/mne-tools/mne-python/pull/${PR_NUM}" >> $GITHUB_STEP_SUMMARY if: steps.status.outputs.dirty == 'true' diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a33d5590cec..8975e72784b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -120,11 +120,11 @@ jobs: - run: ./tools/github_actions_dependencies.sh # Minimal commands on Linux (macOS stalls) - run: ./tools/get_minimal_commands.sh - if: ${{ startswith(matrix.os, 'ubuntu') }} + if: startswith(matrix.os, 'ubuntu') && matrix.kind != 'minimal' && matrix.kind != 'old' - run: ./tools/github_actions_infos.sh # Check Qt - run: ./tools/check_qt_import.sh $MNE_QT_BACKEND - if: ${{ env.MNE_QT_BACKEND != '' }} + if: env.MNE_QT_BACKEND != '' - name: Run tests with no testing data run: MNE_SKIP_TESTING_DATASET_TESTS=true pytest -m "not (ultraslowtest or pgtest)" --tb=short --cov=mne --cov-report xml -vv -rfE mne/ if: matrix.kind == 'minimal' diff --git a/.mailmap b/.mailmap index 327f5a9a648..133eb2be306 100644 --- a/.mailmap +++ b/.mailmap @@ -2,6 +2,7 @@ Adam Li Adam Li Adam Li Adam Li Alan Leggitt leggitta Alessandro Tonin Lychfindel <58313635+Lychfindel@users.noreply.github.com> +Alex Lepauvre Alex lepauvre Alex Rockhill Alex Alex Rockhill Alex Alex Rockhill Alex Rockhill @@ -356,4 +357,4 @@ Yousra Bekhti Yousra BEKHTI Yousra Bekhti yousrabk Zhi Zhang <850734033@qq.com> ZHANG Zhi <850734033@qq.com> Zhi Zhang <850734033@qq.com> ZHANG Zhi -Ziyi ZENG +Ziyi ZENG ZIYI ZENG diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e11e392ae25..e7a931b5713 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ repos: # Ruff mne - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.8.2 + rev: v0.8.3 hooks: - id: ruff name: ruff lint mne @@ -82,7 +82,7 @@ repos: # zizmor - repo: https://github.com/woodruffw/zizmor-pre-commit - rev: v0.8.0 + rev: v0.9.2 hooks: - id: zizmor diff --git a/CITATION.cff b/CITATION.cff index a55d21e00c0..2ba5fd6b4c6 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,9 +1,9 @@ cff-version: 1.2.0 title: "MNE-Python" message: "If you use this software, please cite both the software itself, and the paper listed in the preferred-citation field." -version: 1.8.0 -date-released: "2024-08-18" -commit: 9a760d76971e845b67b619804c1156cc04c9c948 +version: 1.9.0 +date-released: "2024-12-18" +commit: 14938b9657b255a38aa96482a4aaf410e8865859 doi: 10.5281/zenodo.592483 keywords: - MEG @@ -40,15 +40,15 @@ authors: - family-names: Luessi given-names: Martin - family-names: King - given-names: Jean-Remi + given-names: Jean-Rémi - family-names: Höchenberger given-names: Richard - family-names: Goj given-names: Roman - - family-names: Favelier - given-names: Guillaume - family-names: Brunner given-names: Clemens + - family-names: Favelier + given-names: Guillaume - family-names: van Vliet given-names: Marijn - family-names: Wronkiewicz @@ -57,22 +57,22 @@ authors: given-names: Alex - family-names: Holdgraf given-names: Chris - - family-names: Massich - given-names: Joan - - family-names: Bekhti - given-names: Yousra - family-names: Scheltienne given-names: Mathieu + - family-names: Massich + given-names: Joan - family-names: Appelhoff given-names: Stefan + - family-names: Bekhti + given-names: Yousra - family-names: Leggitt given-names: Alan - family-names: Dykstra given-names: Andrew - - family-names: Luke - given-names: Rob - family-names: Trachel given-names: Romain + - family-names: Luke + given-names: Robert - family-names: De Santis given-names: Lorenzo - family-names: Panda @@ -111,12 +111,12 @@ authors: given-names: Jair - family-names: Woodman given-names: Marmaduke + - family-names: Huberty + given-names: Scott - family-names: Lee given-names: Ingoo - family-names: Schulz given-names: Martin - - family-names: Huberty - given-names: Scott - family-names: Foti given-names: Nick - family-names: Nangini @@ -156,6 +156,8 @@ authors: given-names: Ana - family-names: Buran given-names: Brad + - family-names: Woessner + given-names: Jacob - family-names: Massias given-names: Mathurin - family-names: Hämäläinen @@ -168,8 +170,6 @@ authors: given-names: Christopher - family-names: Raimundo given-names: Félix - - family-names: Woessner - given-names: Jacob - family-names: Kaneda given-names: Michiru - family-names: Alday @@ -192,6 +192,8 @@ authors: given-names: Mads - family-names: Gahlot given-names: Tanay + - family-names: Binns + given-names: Thomas S - family-names: Nunes given-names: Adonay - family-names: Gütlin @@ -221,6 +223,10 @@ authors: given-names: Natalie - family-names: Roujansky given-names: Paul + - family-names: Luke + given-names: Rob + - family-names: Ruuskanen + given-names: Santeri - family-names: Kern given-names: Simon - family-names: Rantala @@ -275,10 +281,10 @@ authors: given-names: Nathalie - family-names: Ward given-names: Nick - - family-names: Ruuskanen - given-names: Santeri - family-names: Herbst given-names: Sophie + - family-names: Férat + given-names: Victor - family-names: Radanovic given-names: Ana - family-names: Quinn @@ -299,6 +305,8 @@ authors: given-names: Evgenii - family-names: Mamashli given-names: Fahimeh + - family-names: Belonosov + given-names: Gennadiy - family-names: O'Neill given-names: George - family-names: Marinato @@ -327,6 +335,8 @@ authors: given-names: Nicolas - family-names: Kapralov given-names: Nikolai + - family-names: Chu + given-names: Qian - family-names: Falach given-names: Rotem - family-names: Deslauriers-Gauthier @@ -337,14 +347,10 @@ authors: given-names: Steve - family-names: Bierer given-names: Steven - - family-names: Binns - given-names: Thomas S - family-names: Binns given-names: Thomas Samuel - family-names: Stenner given-names: Tristan - - family-names: Férat - given-names: Victor - family-names: Peterson given-names: Victoria - family-names: Baratz @@ -369,8 +375,8 @@ authors: given-names: Dominique - family-names: Mikulan given-names: Ezequiel - - family-names: Belonosov - given-names: Gennadiy + - family-names: Hofer + given-names: Florian - family-names: Schiratti given-names: Jean-Baptiste - family-names: Evans @@ -416,12 +422,14 @@ authors: given-names: Peter J - family-names: Ablin given-names: Pierre - - family-names: Chu - given-names: Qian + - family-names: Das + given-names: Proloy - family-names: Bertrand given-names: Quentin - family-names: Shoorangiz given-names: Reza + - family-names: Scholz + given-names: Richard - family-names: Hübner given-names: Rodrigo - family-names: Sommariva @@ -460,6 +468,8 @@ authors: given-names: Adina - family-names: Ciok given-names: Alex + - family-names: Lepauvre + given-names: Alex - family-names: Kiefer given-names: Alexander - family-names: Gilbert @@ -534,12 +544,12 @@ authors: given-names: Etienne - family-names: Goldstein given-names: Evgeny + - family-names: Mamashli + given-names: Fahimeh - family-names: Negahbani given-names: Farzin - family-names: Zamberlan given-names: Federico - - family-names: Hofer - given-names: Florian - family-names: Pop given-names: Florin - family-names: Weber @@ -573,6 +583,8 @@ authors: given-names: Ivan - family-names: de Jong given-names: Ivo + - family-names: Phelan + given-names: Jacob - family-names: Kaczmarzyk given-names: Jakub - family-names: Zerfowski @@ -603,6 +615,8 @@ authors: given-names: Laetitia - family-names: Andersen given-names: Lau Møller + - family-names: Almeida + given-names: Leonardo Rochael - family-names: Barbosa given-names: Leonardo S - family-names: Alfine @@ -671,8 +685,6 @@ authors: given-names: Padma - family-names: Silva given-names: Pedro - - family-names: Das - given-names: Proloy - family-names: Li given-names: Quanliang - family-names: Barthélemy @@ -689,8 +701,6 @@ authors: given-names: Reza - family-names: Koehler given-names: Richard - - family-names: Scholz - given-names: Richard - family-names: Stargardsky given-names: Riessarius - family-names: Oostenveld @@ -727,6 +737,8 @@ authors: given-names: Simeon - family-names: Wong given-names: Simeon + - family-names: Hofmann + given-names: Simon M - family-names: Poil given-names: Simon-Shlomo - family-names: Foslien @@ -769,6 +781,8 @@ authors: given-names: Yiping - family-names: Zhang given-names: Zhi + - family-names: ZENG + given-names: Ziyi - name: btkcodedev - name: buildqa - name: luzpaz diff --git a/SECURITY.md b/SECURITY.md index 82d4c9e45de..a8e59476a67 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -10,9 +10,9 @@ without a proper 6-month deprecation cycle. | Version | Supported | | ------- | ------------------------ | -| 1.8.x | :heavy_check_mark: (dev) | -| 1.7.x | :heavy_check_mark: | -| < 1.7 | :x: | +| 1.9.x | :heavy_check_mark: (dev) | +| 1.8.x | :heavy_check_mark: | +| < 1.8 | :x: | ## Reporting a Vulnerability diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 40e214102e1..3ca4177174f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -171,8 +171,7 @@ stages: python -m pip install --progress-bar off --upgrade pip python -m pip install --progress-bar off --upgrade --pre --only-binary=\"numpy,scipy,matplotlib,vtk\" numpy scipy matplotlib vtk python -c "import vtk" - # Bug on 2.5.13 https://github.com/openmeeg/openmeeg/issues/700 - python -m pip install --progress-bar off --upgrade -ve .[full,test_extra] "openmeeg==2.5.12" + python -m pip install --progress-bar off --upgrade -ve .[full,test_extra] displayName: 'Install dependencies with pip' - bash: | set -e diff --git a/codemeta.json b/codemeta.json index 0351ca98a1c..d5ec88c23e9 100644 --- a/codemeta.json +++ b/codemeta.json @@ -5,11 +5,11 @@ "codeRepository": "git+https://github.com/mne-tools/mne-python.git", "dateCreated": "2010-12-26", "datePublished": "2014-08-04", - "dateModified": "2024-08-18", - "downloadUrl": "https://github.com/mne-tools/mne-python/archive/v1.8.0.zip", + "dateModified": "2024-12-18", + "downloadUrl": "https://github.com/mne-tools/mne-python/archive/v1.9.0.zip", "issueTracker": "https://github.com/mne-tools/mne-python/issues", "name": "MNE-Python", - "version": "1.8.0", + "version": "1.9.0", "description": "MNE-Python is an open-source Python package for exploring, visualizing, and analyzing human neurophysiological data. It provides methods for data input/output, preprocessing, visualization, source estimation, time-frequency analysis, connectivity analysis, machine learning, and statistics.", "applicationCategory": "Neuroscience", "developmentStatus": "active", @@ -37,16 +37,16 @@ "macOS" ], "softwareRequirements": [ - "python>=3.9", - "numpy>=1.23,<3", - "scipy>=1.9", - "matplotlib>=3.6", - "tqdm", - "pooch>=1.5", + "python>= 3.10", "decorator", - "packaging", "jinja2", - "lazy_loader>=0.3" + "lazy_loader >= 0.3", + "matplotlib >= 3.6", + "numpy >= 1.23,<3", + "packaging", + "pooch >= 1.5", + "scipy >= 1.9", + "tqdm" ], "author": [ { @@ -112,7 +112,7 @@ { "@type":"Person", "email":"jeanremi.king+github@gmail.com", - "givenName":"Jean-Remi", + "givenName":"Jean-Rémi", "familyName": "King" }, { @@ -127,18 +127,18 @@ "givenName":"Roman", "familyName": "Goj" }, - { - "@type":"Person", - "email":"guillaume.favelier@gmail.com", - "givenName":"Guillaume", - "familyName": "Favelier" - }, { "@type":"Person", "email":"clemens.brunner@gmail.com", "givenName":"Clemens", "familyName": "Brunner" }, + { + "@type":"Person", + "email":"guillaume.favelier@gmail.com", + "givenName":"Guillaume", + "familyName": "Favelier" + }, { "@type":"Person", "email":"w.m.vanvliet@gmail.com", @@ -163,30 +163,30 @@ "givenName":"Chris", "familyName": "Holdgraf" }, - { - "@type":"Person", - "email":"mailsik@gmail.com", - "givenName":"Joan", - "familyName": "Massich" - }, - { - "@type":"Person", - "email":"yousra.bekhti@gmail.com", - "givenName":"Yousra", - "familyName": "Bekhti" - }, { "@type":"Person", "email":"mathieu.scheltienne@gmail.com", "givenName":"Mathieu", "familyName": "Scheltienne" }, + { + "@type":"Person", + "email":"mailsik@gmail.com", + "givenName":"Joan", + "familyName": "Massich" + }, { "@type":"Person", "email":"stefan.appelhoff@mailbox.org", "givenName":"Stefan", "familyName": "Appelhoff" }, + { + "@type":"Person", + "email":"yousra.bekhti@gmail.com", + "givenName":"Yousra", + "familyName": "Bekhti" + }, { "@type":"Person", "email":"leggitta3@gmail.com", @@ -199,18 +199,18 @@ "givenName":"Andrew", "familyName": "Dykstra" }, - { - "@type":"Person", - "email":"code@robertluke.net", - "givenName":"Rob", - "familyName": "Luke" - }, { "@type":"Person", "email":"romain.trachel@inria.fr", "givenName":"Romain", "familyName": "Trachel" }, + { + "@type":"Person", + "email":"code@robertluke.net", + "givenName":"Robert", + "familyName": "Luke" + }, { "@type":"Person", "email":"desantis.lnz@gmail.com", @@ -325,6 +325,12 @@ "givenName":"Marmaduke", "familyName": "Woodman" }, + { + "@type":"Person", + "email":"", + "givenName":"Scott", + "familyName": "Huberty" + }, { "@type":"Person", "email":"dlsrnsladlek@naver.com", @@ -337,12 +343,6 @@ "givenName":"Martin", "familyName": "Schulz" }, - { - "@type":"Person", - "email":"", - "givenName":"Scott", - "familyName": "Huberty" - }, { "@type":"Person", "email":"nfoti01@gmail.com", @@ -463,6 +463,12 @@ "givenName":"Brad", "familyName": "Buran" }, + { + "@type":"Person", + "email":"Woessner.jacob@gmail.com", + "givenName":"Jacob", + "familyName": "Woessner" + }, { "@type":"Person", "email":"mathurin.massias@gmail.com", @@ -499,12 +505,6 @@ "givenName":"Félix", "familyName": "Raimundo" }, - { - "@type":"Person", - "email":"Woessner.jacob@gmail.com", - "givenName":"Jacob", - "familyName": "Woessner" - }, { "@type":"Person", "email":"rcmdnk@gmail.com", @@ -571,6 +571,12 @@ "givenName":"Tanay", "familyName": "Gahlot" }, + { + "@type":"Person", + "email":"t.s.binns@outlook.com", + "givenName":"Thomas S", + "familyName": "Binns" + }, { "@type":"Person", "email":"adonay.s.nunes@gmail.com", @@ -661,6 +667,18 @@ "givenName":"Paul", "familyName": "Roujansky" }, + { + "@type":"Person", + "email":"code@robertluke.net", + "givenName":"Rob", + "familyName": "Luke" + }, + { + "@type":"Person", + "email":"santeri.ruuskanen@aalto.fi", + "givenName":"Santeri", + "familyName": "Ruuskanen" + }, { "@type":"Person", "email":"simon.kern@online.de", @@ -823,18 +841,18 @@ "givenName":"Nick", "familyName": "Ward" }, - { - "@type":"Person", - "email":"santeri.ruuskanen@aalto.fi", - "givenName":"Santeri", - "familyName": "Ruuskanen" - }, { "@type":"Person", "email":"ksherbst@gmail.com", "givenName":"Sophie", "familyName": "Herbst" }, + { + "@type":"Person", + "email":"victor.ferat@live.Fr", + "givenName":"Victor", + "familyName": "Férat" + }, { "@type":"Person", "email":"", @@ -895,6 +913,12 @@ "givenName":"Fahimeh", "familyName": "Mamashli" }, + { + "@type":"Person", + "email":"", + "givenName":"Gennadiy", + "familyName": "Belonosov" + }, { "@type":"Person", "email":"g.o'neill@ucl.ac.uk", @@ -979,6 +1003,12 @@ "givenName":"Nikolai", "familyName": "Kapralov" }, + { + "@type":"Person", + "email":"", + "givenName":"Qian", + "familyName": "Chu" + }, { "@type":"Person", "email":"falachrotem@gmail.com", @@ -1009,12 +1039,6 @@ "givenName":"Steven", "familyName": "Bierer" }, - { - "@type":"Person", - "email":"t.s.binns@outlook.com", - "givenName":"Thomas S", - "familyName": "Binns" - }, { "@type":"Person", "email":"t.s.binns@outlook.com", @@ -1027,12 +1051,6 @@ "givenName":"Tristan", "familyName": "Stenner" }, - { - "@type":"Person", - "email":"victor.ferat@live.Fr", - "givenName":"Victor", - "familyName": "Férat" - }, { "@type":"Person", "email":"victoriapeterson09@gmail.com", @@ -1107,9 +1125,9 @@ }, { "@type":"Person", - "email":"", - "givenName":"Gennadiy", - "familyName": "Belonosov" + "email":"hofaflo@gmail.com", + "givenName":"Florian", + "familyName": "Hofer" }, { "@type":"Person", @@ -1251,9 +1269,9 @@ }, { "@type":"Person", - "email":"", - "givenName":"Qian", - "familyName": "Chu" + "email":"proloy@umd.edu", + "givenName":"Proloy", + "familyName": "Das" }, { "@type":"Person", @@ -1267,6 +1285,12 @@ "givenName":"Reza", "familyName": "Shoorangiz" }, + { + "@type":"Person", + "email":"", + "givenName":"Richard", + "familyName": "Scholz" + }, { "@type":"Person", "email":"rhubner@gmail.com", @@ -1387,6 +1411,12 @@ "givenName":"Alex", "familyName": "Ciok" }, + { + "@type":"Person", + "email":"alex.lepauvre@ae.mpg.de", + "givenName":"Alex", + "familyName": "Lepauvre" + }, { "@type":"Person", "email":"", @@ -1609,6 +1639,12 @@ "givenName":"Evgeny", "familyName": "Goldstein" }, + { + "@type":"Person", + "email":"fmamashli@gmail.com", + "givenName":"Fahimeh", + "familyName": "Mamashli" + }, { "@type":"Person", "email":"farzin.negahbani@gmail.com", @@ -1621,12 +1657,6 @@ "givenName":"Federico", "familyName": "Zamberlan" }, - { - "@type":"Person", - "email":"hofaflo@gmail.com", - "givenName":"Florian", - "familyName": "Hofer" - }, { "@type":"Person", "email":"florinpop@me.com", @@ -1729,6 +1759,12 @@ "givenName":"Ivo", "familyName": "de Jong" }, + { + "@type":"Person", + "email":"jacob.phelan.jp@gmail.com", + "givenName":"Jacob", + "familyName": "Phelan" + }, { "@type":"Person", "email":"", @@ -1819,6 +1855,12 @@ "givenName":"Lau Møller", "familyName": "Andersen" }, + { + "@type":"Person", + "email":"leorochael@gmail.com", + "givenName":"Leonardo Rochael", + "familyName": "Almeida" + }, { "@type":"Person", "email":"lsbarbosa@gmail.com", @@ -2023,12 +2065,6 @@ "givenName":"Pedro", "familyName": "Silva" }, - { - "@type":"Person", - "email":"proloy@umd.edu", - "givenName":"Proloy", - "familyName": "Das" - }, { "@type":"Person", "email":"glia@dtu.dk", @@ -2077,12 +2113,6 @@ "givenName":"Richard", "familyName": "Koehler" }, - { - "@type":"Person", - "email":"", - "givenName":"Richard", - "familyName": "Scholz" - }, { "@type":"Person", "email":"rie.acad@gmail.com", @@ -2191,6 +2221,12 @@ "givenName":"Simeon", "familyName": "Wong" }, + { + "@type":"Person", + "email":"", + "givenName":"Simon M", + "familyName": "Hofmann" + }, { "@type":"Person", "email":"", @@ -2317,6 +2353,12 @@ "givenName":"Zhi", "familyName": "Zhang" }, + { + "@type":"Person", + "email":"ziyizeng@link.cuhk.edu.cn", + "givenName":"Ziyi", + "familyName": "ZENG" + }, { "@type":"Person", "email":"btk.codedev@gmail.com", diff --git a/doc/_static/versions.json b/doc/_static/versions.json index ba4f9fc5d99..478677634c0 100644 --- a/doc/_static/versions.json +++ b/doc/_static/versions.json @@ -1,14 +1,19 @@ [ { - "name": "1.9 (devel)", + "name": "1.10 (devel)", "version": "dev", "url": "https://mne.tools/dev/" }, { - "name": "1.8 (stable)", + "name": "1.9 (stable)", "version": "stable", "url": "https://mne.tools/stable/" }, + { + "name": "1.8", + "version": "1.8", + "url": "https://mne.tools/1.8/" + }, { "name": "1.7", "version": "1.7", diff --git a/doc/changes/devel/12366.newfeature.rst b/doc/changes/devel/12366.newfeature.rst deleted file mode 100644 index 979c7141504..00000000000 --- a/doc/changes/devel/12366.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for `dict` type argument ``ref_channels`` to :func:`mne.set_eeg_reference`, to allow flexible re-referencing (e.g. ``raw.set_eeg_reference(ref_channels={'A1': ['A2', 'A3']})`` will set the new A1 data to be ``A1 - mean(A2, A3)``), by `Alex Lepauvre`_ and `Qian Chu`_ and `Daniel McCloy`_. \ No newline at end of file diff --git a/doc/changes/devel/12787.other.rst b/doc/changes/devel/12787.other.rst deleted file mode 100644 index 1f53fdea066..00000000000 --- a/doc/changes/devel/12787.other.rst +++ /dev/null @@ -1 +0,0 @@ -Use custom code in :func:`mne.sys_info` to get the amount of physical memory and a more informative CPU name instead of using the ``psutil`` package, by `Clemens Brunner`_. \ No newline at end of file diff --git a/doc/changes/devel/12792.newfeature.rst b/doc/changes/devel/12792.newfeature.rst deleted file mode 100644 index 81ef79c8a11..00000000000 --- a/doc/changes/devel/12792.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add reader for ANT Neuro files in the ``*.cnt`` format with :func:`~mne.io.read_raw_ant`, by `Mathieu Scheltienne`_, `Eric Larson`_ and `Proloy Das`_. diff --git a/doc/changes/devel/12798.dependency.rst b/doc/changes/devel/12798.dependency.rst deleted file mode 100644 index ef05dab1e8d..00000000000 --- a/doc/changes/devel/12798.dependency.rst +++ /dev/null @@ -1 +0,0 @@ -- Minimum supported dependencies were updated in accordance with SPEC0_, most notably Python 3.10+ is now required. diff --git a/doc/changes/devel/12801.newfeature.rst b/doc/changes/devel/12801.newfeature.rst deleted file mode 100644 index 5f81e025c52..00000000000 --- a/doc/changes/devel/12801.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -- Add support for a :class:`mne.transforms.Transform` in the argument ``trans`` of the coregistration GUI called with :func:`mne.gui.coregistration`, by `Mathieu Scheltienne`_. diff --git a/doc/changes/devel/12803.bugfix.rst b/doc/changes/devel/12803.bugfix.rst deleted file mode 100644 index c10bddd517b..00000000000 --- a/doc/changes/devel/12803.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix handling of MRI file-path in :class:`mne.SourceSpaces` and safeguard saving of :class:`pathlib.Path` with ``h5io`` by casting to :class:`str`, by `Mathieu Scheltienne`_. diff --git a/doc/changes/devel/12804.bugfix.rst b/doc/changes/devel/12804.bugfix.rst deleted file mode 100644 index 87a988a4525..00000000000 --- a/doc/changes/devel/12804.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Cast ``fwd["info"]`` to :class:`~mne.Info` and ``fwd["src"]`` to :class:`~mne.SourceSpaces` when loading a forward solution from an HDF5 file, by `Mathieu Scheltienne`_. diff --git a/doc/changes/devel/12805.newfeature.rst b/doc/changes/devel/12805.newfeature.rst deleted file mode 100644 index 2c77d55d3ba..00000000000 --- a/doc/changes/devel/12805.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Added support for ``sensor_scales`` to :meth:`mne.viz.Brain.add_sensors` and :func:`mne.viz.plot_alignment`, by :newcontrib:`Alex Lepauvre`. \ No newline at end of file diff --git a/doc/changes/devel/12811.newfeature.rst b/doc/changes/devel/12811.newfeature.rst deleted file mode 100644 index def54b1a68b..00000000000 --- a/doc/changes/devel/12811.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`~mne.io.Raw` and :meth:`~mne.Epochs.save` now return the path to the saved file(s), by `Victor Ferat`_. diff --git a/doc/changes/devel/12827.other.rst b/doc/changes/devel/12827.other.rst deleted file mode 100644 index 3ccbaa0bff6..00000000000 --- a/doc/changes/devel/12827.other.rst +++ /dev/null @@ -1 +0,0 @@ -Improve documentation clarity of ``fit_transform`` methods for :class:`mne.decoding.SSD`, :class:`mne.decoding.CSP`, and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. \ No newline at end of file diff --git a/doc/changes/devel/12829.apichange.rst b/doc/changes/devel/12829.apichange.rst deleted file mode 100644 index d0bd4c12a46..00000000000 --- a/doc/changes/devel/12829.apichange.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate ``average`` parameter in ``plot_filters`` and ``plot_patterns`` methods of the :class:`mne.decoding.CSP` and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. \ No newline at end of file diff --git a/doc/changes/devel/12830.newfeature.rst b/doc/changes/devel/12830.newfeature.rst deleted file mode 100644 index 4d51229392d..00000000000 --- a/doc/changes/devel/12830.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -:func:`mne.channels.read_custom_montage` may now read a newer version of the ``.elc`` ASA Electrode file format, by `Stefan Appelhoff`_. diff --git a/doc/changes/devel/12834.dependency.rst b/doc/changes/devel/12834.dependency.rst deleted file mode 100644 index ca19423df87..00000000000 --- a/doc/changes/devel/12834.dependency.rst +++ /dev/null @@ -1,2 +0,0 @@ -Importing from ``mne.decoding`` now explicitly requires ``scikit-learn`` to be installed, -by `Eric Larson`_. diff --git a/doc/changes/devel/12842.bugfix.rst b/doc/changes/devel/12842.bugfix.rst deleted file mode 100644 index 75f83683b8f..00000000000 --- a/doc/changes/devel/12842.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug where :meth:`mne.Epochs.compute_tfr` could not be used with the multitaper method and complex or phase outputs, by `Thomas Binns`_. \ No newline at end of file diff --git a/doc/changes/devel/12843.bugfix.rst b/doc/changes/devel/12843.bugfix.rst deleted file mode 100644 index 6f3be428b3a..00000000000 --- a/doc/changes/devel/12843.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fixed a bug where split FIF files that were read and then appended to other -:class:`mne.io.Raw` instances had their ``BAD boundary`` annotations incorrectly offset -in samples by the number of split files, by `Eric Larson`_. diff --git a/doc/changes/devel/12843.other.rst b/doc/changes/devel/12843.other.rst deleted file mode 100644 index 5271d6124de..00000000000 --- a/doc/changes/devel/12843.other.rst +++ /dev/null @@ -1 +0,0 @@ -Improve handling of filenames in ``raw.filenames`` by using :class:`~pathlib.Path` instead of :class:`str`, by `Mathieu Scheltienne`_. diff --git a/doc/changes/devel/12844.other.rst b/doc/changes/devel/12844.other.rst deleted file mode 100644 index ce959d8132a..00000000000 --- a/doc/changes/devel/12844.other.rst +++ /dev/null @@ -1 +0,0 @@ -Improve automatic figure scaling of :func:`mne.viz.plot_events`, and event_id and count overview legend when a high amount of unique events is supplied, by `Stefan Appelhoff`_. diff --git a/doc/changes/devel/12846.bugfix.rst b/doc/changes/devel/12846.bugfix.rst deleted file mode 100644 index ce18e8f5201..00000000000 --- a/doc/changes/devel/12846.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Enforce SI units for Eyetracking data (eyegaze data should be radians of visual angle, not pixels. Pupil size data should be meters). -Updated tutorials so demonstrate how to convert data to SI units before analyses, by `Scott Huberty`_. \ No newline at end of file diff --git a/doc/changes/devel/12853.bugfix.rst b/doc/changes/devel/12853.bugfix.rst deleted file mode 100644 index 18c8afbb8ea..00000000000 --- a/doc/changes/devel/12853.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Prevent the ``colorbar`` parameter being ignored in topomap plots such as :meth:`mne.time_frequency.Spectrum.plot_topomap`, by `Thomas Binns`_. \ No newline at end of file diff --git a/doc/changes/devel/12862.other.rst b/doc/changes/devel/12862.other.rst deleted file mode 100644 index 393beeb8a8c..00000000000 --- a/doc/changes/devel/12862.other.rst +++ /dev/null @@ -1 +0,0 @@ -:meth:`mne.preprocessing.ICA.find_bads_muscle` can now be run when passing an ``inst`` without sensor positions. However, it will just use the first of three criteria (slope) to find muscle-related ICA components, by `Stefan Appelhoff`_. diff --git a/doc/changes/devel/12871.newfeature.rst b/doc/changes/devel/12871.newfeature.rst deleted file mode 100644 index 7c6f9e6c9df..00000000000 --- a/doc/changes/devel/12871.newfeature.rst +++ /dev/null @@ -1,2 +0,0 @@ -Added the ``title`` argument to :func:`mne.viz.create_3d_figure`, and -``color`` and ``position`` arguments to :func:`mne.viz.set_3d_title`, by `Eric Larson`_. diff --git a/doc/changes/devel/12875.bugfix.rst b/doc/changes/devel/12875.bugfix.rst deleted file mode 100644 index c4fa57e9100..00000000000 --- a/doc/changes/devel/12875.bugfix.rst +++ /dev/null @@ -1,2 +0,0 @@ -Fix bug where invalid data types (e.g., ``np.ndarray``s) could be used in some -:class:`mne.io.Info` fields like ``info["subject_info"]["weight"]``, by `Eric Larson`_. \ No newline at end of file diff --git a/doc/changes/devel/12877.bugfix.rst b/doc/changes/devel/12877.bugfix.rst deleted file mode 100644 index 2d9ecf2c489..00000000000 --- a/doc/changes/devel/12877.bugfix.rst +++ /dev/null @@ -1,4 +0,0 @@ -When creating a :class:`~mne.time_frequency.SpectrumArray`, the array shape check now -compares against the total of both 'good' and 'bad' channels in the provided -:class:`~mne.Info` (previously only good channels were checked), by -`Mathieu Scheltienne`_. diff --git a/doc/changes/devel/12884.bugfix.rst b/doc/changes/devel/12884.bugfix.rst deleted file mode 100644 index 6c5beda7241..00000000000 --- a/doc/changes/devel/12884.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug where :ref:`mne coreg` would always show MEG channels even if the "MEG Sensors" checkbox was disabled, by `Eric Larson`_. diff --git a/doc/changes/devel/12896.other.rst b/doc/changes/devel/12896.other.rst deleted file mode 100644 index 7ad9ff17a63..00000000000 --- a/doc/changes/devel/12896.other.rst +++ /dev/null @@ -1 +0,0 @@ -Update governance model, by `Daniel McCloy`_. diff --git a/doc/changes/devel/12901.bugfix.rst b/doc/changes/devel/12901.bugfix.rst deleted file mode 100644 index d68f70f7141..00000000000 --- a/doc/changes/devel/12901.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -:class:`mne.Report` HDF5 files are now written in ``mode='a'`` (append) to allow users to store other data in the HDF5 files, by `Eric Larson`_. diff --git a/doc/changes/devel/12901.newfeature.rst b/doc/changes/devel/12901.newfeature.rst deleted file mode 100644 index 8d0137fce78..00000000000 --- a/doc/changes/devel/12901.newfeature.rst +++ /dev/null @@ -1,8 +0,0 @@ -Improved reporting and plotting options: - -- :meth:`mne.Report.add_projs` can now plot with :func:`mne.viz.plot_projs_joint` rather than :func:`mne.viz.plot_projs_topomap` -- :class:`mne.Report` now has attributes ``img_max_width`` and ``img_max_res`` that can be used to control image scaling. -- :class:`mne.Report` now has an attribute ``collapse`` that allows collapsing sections and/or subsections by default. -- :func:`mne.viz.plot_head_positions` now has a ``totals=True`` option to show the total distance and angle of the head. - -Changes by `Eric Larson`_. diff --git a/doc/changes/devel/12909.bugfix.rst b/doc/changes/devel/12909.bugfix.rst deleted file mode 100644 index 9e2f5672323..00000000000 --- a/doc/changes/devel/12909.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix bug in :func:`mne.io.read_raw_gdf` when NumPy >= 2 is used, by `Clemens Brunner`_. \ No newline at end of file diff --git a/doc/changes/devel/12911.bugfix.rst b/doc/changes/devel/12911.bugfix.rst deleted file mode 100644 index c04a23d645d..00000000000 --- a/doc/changes/devel/12911.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Allow exporting edf where a channel contains only constant values, by `Florian Hofer`_. diff --git a/doc/changes/devel/12912.newfeature.rst b/doc/changes/devel/12912.newfeature.rst deleted file mode 100644 index 2a7343ebd2c..00000000000 --- a/doc/changes/devel/12912.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Added the ``psd_args`` argument to :func:`mne.viz.plot_ica_sources` and :meth:`mne.preprocessing.ICA.plot_sources`, by `Richard Scholz`_. \ No newline at end of file diff --git a/doc/changes/devel/12918.apichange.rst b/doc/changes/devel/12918.apichange.rst deleted file mode 100644 index 958662b1b6f..00000000000 --- a/doc/changes/devel/12918.apichange.rst +++ /dev/null @@ -1 +0,0 @@ -Deprecate ``subject`` parameter in favor of ``subjects`` in :func:`mne.datasets.eegbci.load_data`, by `Stefan Appelhoff`_. diff --git a/doc/changes/devel/12924.bugfix.rst b/doc/changes/devel/12924.bugfix.rst deleted file mode 100644 index 57afa60fbd8..00000000000 --- a/doc/changes/devel/12924.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix typos in the Spatio-Spectral Decomposition example, by :newcontrib:`Simon M. Hofmann`. \ No newline at end of file diff --git a/doc/changes/devel/12931.bugfix.rst b/doc/changes/devel/12931.bugfix.rst deleted file mode 100644 index 7c41cd03a7d..00000000000 --- a/doc/changes/devel/12931.bugfix.rst +++ /dev/null @@ -1,3 +0,0 @@ -Fix a bug in :func:`mne.epochs.make_metadata`, where missing values in the columns -generated for ``keep_first`` and ``keep_last`` events were represented by empty strings, -while it should have been ``NA`` values, by `Richard Höchenberger`_. diff --git a/doc/changes/devel/12931.other.rst b/doc/changes/devel/12931.other.rst deleted file mode 100644 index bf0a83534ad..00000000000 --- a/doc/changes/devel/12931.other.rst +++ /dev/null @@ -1 +0,0 @@ -Improve the :ref:`tut-autogenerate-metadata`, by `Clemens Brunner`_ and `Richard Höchenberger`_. diff --git a/doc/changes/devel/12936.bugfix.rst b/doc/changes/devel/12936.bugfix.rst deleted file mode 100644 index 8cb1967d4c4..00000000000 --- a/doc/changes/devel/12936.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix decimal places of :class:`float` ``mne.Evoked.nave`` in :meth:`mne.Evoked.plot` and :meth:`mne.Evoked.plot_image`, by `Gennadiy Belonosov`_. diff --git a/doc/changes/devel/12955.bugfix.rst b/doc/changes/devel/12955.bugfix.rst deleted file mode 100644 index 924944da9dd..00000000000 --- a/doc/changes/devel/12955.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances. For example a duration of 1h is now displayed as ``00:01:00`` rather than ``00:59:60``. By :newcontrib:`Leonardo Rochael Almeida`. diff --git a/doc/changes/devel/12955.newfeature.rst b/doc/changes/devel/12955.newfeature.rst deleted file mode 100644 index 8ab68c9a138..00000000000 --- a/doc/changes/devel/12955.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add convenience :attr:`mne.io.Raw.duration` property to centralize duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances, by :newcontrib:`Leonardo Rochael Almeida`. diff --git a/doc/changes/devel/12960.other.rst b/doc/changes/devel/12960.other.rst deleted file mode 100644 index 5d136d8e1d8..00000000000 --- a/doc/changes/devel/12960.other.rst +++ /dev/null @@ -1 +0,0 @@ -Mention some gotchas that arise from the fact that by default, we pool across dipole orientations when performing source estimation, by `Marijn van Vliet`_ diff --git a/doc/changes/devel/12962.bugfix.rst b/doc/changes/devel/12962.bugfix.rst deleted file mode 100644 index cf70d8458ba..00000000000 --- a/doc/changes/devel/12962.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix displayed units in representations of classes such as :class:`mne.io.Raw` to correctly use KiB, MiB, GiB, and so on, by `Clemens Brunner`_. \ No newline at end of file diff --git a/doc/changes/devel/12966.newfeature.rst b/doc/changes/devel/12966.newfeature.rst deleted file mode 100644 index dff334d9b0a..00000000000 --- a/doc/changes/devel/12966.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add ability to use :func:`mne.preprocessing.compute_fine_calibration` with non-Neuromag-style systems, as well as options to control the bad-angle and error tolerances, by `Eric Larson`_. diff --git a/doc/changes/devel/12968.bugfix.rst b/doc/changes/devel/12968.bugfix.rst deleted file mode 100644 index a512cc34ad6..00000000000 --- a/doc/changes/devel/12968.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Gracefully handle invalid patient info when reading EDF files by `Scott Huberty`_. \ No newline at end of file diff --git a/doc/changes/devel/12971.newfeature.rst b/doc/changes/devel/12971.newfeature.rst deleted file mode 100644 index a822dd24ab5..00000000000 --- a/doc/changes/devel/12971.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add support for ``uint16_codec`` argument in :func:`mne.io.read_raw_eeglab` when ``pymatreader`` (which already supported this argument previously) is not installed, by `Clemens Brunner`_. \ No newline at end of file diff --git a/doc/changes/devel/12978.other.rst b/doc/changes/devel/12978.other.rst deleted file mode 100644 index 33e73c2d8f9..00000000000 --- a/doc/changes/devel/12978.other.rst +++ /dev/null @@ -1 +0,0 @@ -Fix a mistake in :ref:`tut-artifact-regression` where the wrong regression coefficients were applied, by :newcontrib:`Jacob Phelan`. diff --git a/doc/changes/devel/12986.bugfix.rst b/doc/changes/devel/12986.bugfix.rst deleted file mode 100644 index 5bacb548fdd..00000000000 --- a/doc/changes/devel/12986.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix IndexError when loading CNT file does not have annotations, by :newcontrib:`Ziyi ZENG`. \ No newline at end of file diff --git a/doc/changes/devel/13003.newfeature.rst b/doc/changes/devel/13003.newfeature.rst deleted file mode 100644 index 141265406a8..00000000000 --- a/doc/changes/devel/13003.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Added support for saving and loading channel names from FIF in :meth:`mne.channels.DigMontage.save` and :meth:`mne.channels.read_dig_fif` and added the convention that they should be saved as ``-dig.fif``, by `Eric Larson`_. diff --git a/doc/changes/devel/13007.bugfix.rst b/doc/changes/devel/13007.bugfix.rst deleted file mode 100644 index e39d44eae5e..00000000000 --- a/doc/changes/devel/13007.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Correct :func:`mne.io.read_raw_cnt` to read responses and fix exceptions by `Jacob Woessner`_. \ No newline at end of file diff --git a/doc/changes/devel/13011.other.rst b/doc/changes/devel/13011.other.rst deleted file mode 100644 index ad66c0cf223..00000000000 --- a/doc/changes/devel/13011.other.rst +++ /dev/null @@ -1 +0,0 @@ -Repository CI security is now audited using `zizmor `__, by `Eric Larson`_. \ No newline at end of file diff --git a/doc/changes/devel/13012.bugfix.rst b/doc/changes/devel/13012.bugfix.rst deleted file mode 100644 index 2d0a324ba06..00000000000 --- a/doc/changes/devel/13012.bugfix.rst +++ /dev/null @@ -1 +0,0 @@ -Fix errant detection of software-rendered vs hardware-rendered MESA GL contexts in 3D rendering on Linux, by `Eric Larson`_. diff --git a/doc/changes/devel/13018.newfeature.rst b/doc/changes/devel/13018.newfeature.rst deleted file mode 100644 index c05878c9071..00000000000 --- a/doc/changes/devel/13018.newfeature.rst +++ /dev/null @@ -1 +0,0 @@ -Add new :meth:`Raw.rescale ` method to rescale the data in place, by `Clemens Brunner`_. \ No newline at end of file diff --git a/doc/changes/devel/13019.newfeature.rst b/doc/changes/devel/13019.newfeature.rst new file mode 100644 index 00000000000..6fe8ee492bf --- /dev/null +++ b/doc/changes/devel/13019.newfeature.rst @@ -0,0 +1 @@ +Add ``fig.mne`` container for :class:`Colorbar ` in :func:`plot_connectivity_circle ` to allow users to access it directly, by `Santeri Ruuskanen`_. \ No newline at end of file diff --git a/doc/changes/devel/13021.dependency.rst b/doc/changes/devel/13021.dependency.rst deleted file mode 100644 index 55681cc06e4..00000000000 --- a/doc/changes/devel/13021.dependency.rst +++ /dev/null @@ -1 +0,0 @@ -Compatibility improved for Python 3.13, by `Eric Larson`_. \ No newline at end of file diff --git a/doc/changes/v1.9.rst b/doc/changes/v1.9.rst new file mode 100644 index 00000000000..17a3a2ba1fe --- /dev/null +++ b/doc/changes/v1.9.rst @@ -0,0 +1,128 @@ +.. _changes_1_9_0: + +1.9.0 (2024-12-18) +================== + +Dependencies +------------ + +- - Minimum supported dependencies were updated in accordance with SPEC0_, most notably Python 3.10+ is now required. (`#12798 `__) +- Importing from ``mne.decoding`` now explicitly requires ``scikit-learn`` to be installed, + by `Eric Larson`_. (`#12834 `__) +- Compatibility improved for Python 3.13, by `Eric Larson`_. (`#13021 `__) + + +Bugfixes +-------- + +- Fix typos in the Spatio-Spectral Decomposition example, by :newcontrib:`Simon M. Hofmann`. (`#12924 `__) +- Fix duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances. For example a duration of 1h is now displayed as ``00:01:00`` rather than ``00:59:60``. By :newcontrib:`Leonardo Rochael Almeida`. (`#12955 `__) +- Fix IndexError when loading CNT file does not have annotations, by :newcontrib:`Ziyi ZENG`. (`#12986 `__) +- Fix handling of MRI file-path in :class:`mne.SourceSpaces` and safeguard saving of :class:`pathlib.Path` with ``h5io`` by casting to :class:`str`, by `Mathieu Scheltienne`_. (`#12803 `__) +- Cast ``fwd["info"]`` to :class:`~mne.Info` and ``fwd["src"]`` to :class:`~mne.SourceSpaces` when loading a forward solution from an HDF5 file, by `Mathieu Scheltienne`_. (`#12804 `__) +- Fix bug where :meth:`mne.Epochs.compute_tfr` could not be used with the multitaper method and complex or phase outputs, by `Thomas Binns`_. (`#12842 `__) +- Fixed a bug where split FIF files that were read and then appended to other + :class:`mne.io.Raw` instances had their ``BAD boundary`` annotations incorrectly offset + in samples by the number of split files, by `Eric Larson`_. (`#12843 `__) +- Enforce SI units for Eyetracking data (eyegaze data should be radians of visual angle, not pixels. Pupil size data should be meters). + Updated tutorials so demonstrate how to convert data to SI units before analyses, by `Scott Huberty`_. (`#12846 `__) +- Prevent the ``colorbar`` parameter being ignored in topomap plots such as :meth:`mne.time_frequency.Spectrum.plot_topomap`, by `Thomas Binns`_. (`#12853 `__) +- Fix bug where invalid data types (e.g., ``np.ndarray``s) could be used in some + :class:`mne.io.Info` fields like ``info["subject_info"]["weight"]``, by `Eric Larson`_. (`#12875 `__) +- When creating a :class:`~mne.time_frequency.SpectrumArray`, the array shape check now + compares against the total of both 'good' and 'bad' channels in the provided + :class:`~mne.Info` (previously only good channels were checked), by + `Mathieu Scheltienne`_. (`#12877 `__) +- Fix bug where :ref:`mne coreg` would always show MEG channels even if the "MEG Sensors" checkbox was disabled, by `Eric Larson`_. (`#12884 `__) +- :class:`mne.Report` HDF5 files are now written in ``mode='a'`` (append) to allow users to store other data in the HDF5 files, by `Eric Larson`_. (`#12901 `__) +- Fix bug in :func:`mne.io.read_raw_gdf` when NumPy >= 2 is used, by `Clemens Brunner`_. (`#12909 `__) +- Allow exporting edf where a channel contains only constant values, by `Florian Hofer`_. (`#12911 `__) +- Fix a bug in :func:`mne.epochs.make_metadata`, where missing values in the columns + generated for ``keep_first`` and ``keep_last`` events were represented by empty strings, + while it should have been ``NA`` values, by `Richard Höchenberger`_. (`#12931 `__) +- Fix decimal places of :class:`float` ``mne.Evoked.nave`` in :meth:`mne.Evoked.plot` and :meth:`mne.Evoked.plot_image`, by `Gennadiy Belonosov`_. (`#12936 `__) +- Fix displayed units in representations of classes such as :class:`mne.io.Raw` to correctly use KiB, MiB, GiB, and so on, by `Clemens Brunner`_. (`#12962 `__) +- Gracefully handle invalid patient info when reading EDF files by `Scott Huberty`_. (`#12968 `__) +- Correct :func:`mne.io.read_raw_cnt` to read responses and fix exceptions by `Jacob Woessner`_. (`#13007 `__) +- Fix errant detection of software-rendered vs hardware-rendered MESA GL contexts in 3D rendering on Linux, by `Eric Larson`_. (`#13012 `__) +- Fix plot scaling for :meth:`Spectrum.plot(dB=True, amplitude=True) `, by `Daniel McCloy`_. (`#13036 `__) + + +API changes by deprecation +-------------------------- + +- Deprecate ``average`` parameter in ``plot_filters`` and ``plot_patterns`` methods of the :class:`mne.decoding.CSP` and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. (`#12829 `__) +- Deprecate ``subject`` parameter in favor of ``subjects`` in :func:`mne.datasets.eegbci.load_data`, by `Stefan Appelhoff`_. (`#12918 `__) + + +New features +------------ + +- Added support for ``sensor_scales`` to :meth:`mne.viz.Brain.add_sensors` and :func:`mne.viz.plot_alignment`, by :newcontrib:`Alex Lepauvre`. (`#12805 `__) +- Add convenience :attr:`mne.io.Raw.duration` property to centralize duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances, by :newcontrib:`Leonardo Rochael Almeida`. (`#12955 `__) +- Add option to :func:`mne.preprocessing.fix_stim_artifact` to use baseline average to flatten TMS pulse artifact by `Fahimeh Mamashli`_ and `Padma Sundaram`_ and `Mohammad Daneshzand`_. (`#6915 `__) +- Add support for `dict` type argument ``ref_channels`` to :func:`mne.set_eeg_reference`, to allow flexible re-referencing (e.g. ``raw.set_eeg_reference(ref_channels={'A1': ['A2', 'A3']})`` will set the new A1 data to be ``A1 - mean(A2, A3)``), by `Alex Lepauvre`_ and `Qian Chu`_ and `Daniel McCloy`_. (`#12366 `__) +- Add reader for ANT Neuro files in the ``*.cnt`` format with :func:`~mne.io.read_raw_ant`, by `Mathieu Scheltienne`_, `Eric Larson`_ and `Proloy Das`_. (`#12792 `__) +- - Add support for a :class:`mne.transforms.Transform` in the argument ``trans`` of the coregistration GUI called with :func:`mne.gui.coregistration`, by `Mathieu Scheltienne`_. (`#12801 `__) +- :meth:`~mne.io.Raw` and :meth:`~mne.Epochs.save` now return the path to the saved file(s), by `Victor Ferat`_. (`#12811 `__) +- :func:`mne.channels.read_custom_montage` may now read a newer version of the ``.elc`` ASA Electrode file format, by `Stefan Appelhoff`_. (`#12830 `__) +- Added the ``title`` argument to :func:`mne.viz.create_3d_figure`, and + ``color`` and ``position`` arguments to :func:`mne.viz.set_3d_title`, by `Eric Larson`_. (`#12871 `__) +- Improved reporting and plotting options: + + - :meth:`mne.Report.add_projs` can now plot with :func:`mne.viz.plot_projs_joint` rather than :func:`mne.viz.plot_projs_topomap` + - :class:`mne.Report` now has attributes ``img_max_width`` and ``img_max_res`` that can be used to control image scaling. + - :class:`mne.Report` now has an attribute ``collapse`` that allows collapsing sections and/or subsections by default. + - :func:`mne.viz.plot_head_positions` now has a ``totals=True`` option to show the total distance and angle of the head. + + Changes by `Eric Larson`_. (`#12901 `__) +- Added the ``psd_args`` argument to :func:`mne.viz.plot_ica_sources` and :meth:`mne.preprocessing.ICA.plot_sources`, by `Richard Scholz`_. (`#12912 `__) +- Add ability to use :func:`mne.preprocessing.compute_fine_calibration` with non-Neuromag-style systems, as well as options to control the bad-angle and error tolerances, by `Eric Larson`_. (`#12966 `__) +- Add support for ``uint16_codec`` argument in :func:`mne.io.read_raw_eeglab` when ``pymatreader`` (which already supported this argument previously) is not installed, by `Clemens Brunner`_. (`#12971 `__) +- Added support for saving and loading channel names from FIF in :meth:`mne.channels.DigMontage.save` and :meth:`mne.channels.read_dig_fif` and added the convention that they should be saved as ``-dig.fif``, by `Eric Larson`_. (`#13003 `__) +- Add new :meth:`Raw.rescale ` method to rescale the data in place, by `Clemens Brunner`_. (`#13018 `__) + + +Other changes +------------- + +- Fix a mistake in :ref:`tut-artifact-regression` where the wrong regression coefficients were applied, by :newcontrib:`Jacob Phelan`. (`#12978 `__) +- Use custom code in :func:`mne.sys_info` to get the amount of physical memory and a more informative CPU name instead of using the ``psutil`` package, by `Clemens Brunner`_. (`#12787 `__) +- Improve documentation clarity of ``fit_transform`` methods for :class:`mne.decoding.SSD`, :class:`mne.decoding.CSP`, and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. (`#12827 `__) +- Improve handling of filenames in ``raw.filenames`` by using :class:`~pathlib.Path` instead of :class:`str`, by `Mathieu Scheltienne`_. (`#12843 `__) +- Improve automatic figure scaling of :func:`mne.viz.plot_events`, and event_id and count overview legend when a high amount of unique events is supplied, by `Stefan Appelhoff`_. (`#12844 `__) +- :meth:`mne.preprocessing.ICA.find_bads_muscle` can now be run when passing an ``inst`` without sensor positions. However, it will just use the first of three criteria (slope) to find muscle-related ICA components, by `Stefan Appelhoff`_. (`#12862 `__) +- Update governance model, by `Daniel McCloy`_. (`#12896 `__) +- Improve the :ref:`tut-autogenerate-metadata`, by `Clemens Brunner`_ and `Richard Höchenberger`_. (`#12931 `__) +- Mention some gotchas that arise from the fact that by default, we pool across dipole orientations when performing source estimation, by `Marijn van Vliet`_ (`#12960 `__) +- Repository CI security is now audited using `zizmor `__, by `Eric Larson`_. (`#13011 `__) + +Authors +------- + +* Alex Lepauvre+ +* Britta Westner +* Clemens Brunner +* Daniel McCloy +* Eric Larson +* Fahimeh Mamashli +* Florian Hofer +* Gennadiy Belonosov +* Jacob Phelan +* Jacob Woessner +* Leonardo Rochael Almeida+ +* Mainak Jas +* Marijn van Vliet +* Mathieu Scheltienne +* Proloy Das +* Qian Chu +* Richard Höchenberger +* Richard Scholz +* Santeri Ruuskanen +* Scott Huberty +* Simon M. Hofmann+ +* Stefan Appelhoff +* Thomas Grainger +* Thomas S. Binns +* Victor Férat +* Ziyi ZENG+ diff --git a/doc/development/whats_new.rst b/doc/development/whats_new.rst index 75ece13b5e0..94b92c0f019 100644 --- a/doc/development/whats_new.rst +++ b/doc/development/whats_new.rst @@ -9,6 +9,7 @@ Changes for each version of MNE-Python are listed below. :maxdepth: 1 ../changes/devel.rst + ../changes/v1.9.rst ../changes/v1.8.rst ../changes/v1.7.rst ../changes/v1.6.rst diff --git a/doc/documentation/cited.rst b/doc/documentation/cited.rst index 565698d9c67..343e28d00ee 100644 --- a/doc/documentation/cited.rst +++ b/doc/documentation/cited.rst @@ -3,7 +3,7 @@ Papers citing MNE-Python ======================== -Estimates provided by Google Scholar as of 18 August 2024: +Estimates provided by Google Scholar as of 16 December 2024: -- `MNE (1810) `_ -- `MNE-Python (2860) `_ +- `MNE (1,900) `_ +- `MNE-Python (3,250) `_ diff --git a/doc/install/installers.rst b/doc/install/installers.rst index c29d09ba132..5b7eeba5203 100644 --- a/doc/install/installers.rst +++ b/doc/install/installers.rst @@ -17,7 +17,7 @@ Platform-specific installers :class-content: text-center :name: install-linux - .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.8.0/MNE-Python-1.8.0_0-Linux.sh + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.9.0/MNE-Python-1.9.0_0-Linux.sh :ref-type: ref :color: primary :shadow: @@ -31,14 +31,14 @@ Platform-specific installers .. code-block:: console - $ sh ./MNE-Python-1.8.0_0-Linux.sh + $ sh ./MNE-Python-1.9.0_0-Linux.sh .. tab-item:: macOS (Intel) :class-content: text-center :name: install-macos-intel - .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.8.0/MNE-Python-1.8.0_0-macOS_Intel.pkg + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.9.0/MNE-Python-1.9.0_0-macOS_Intel.pkg :ref-type: ref :color: primary :shadow: @@ -54,7 +54,7 @@ Platform-specific installers :class-content: text-center :name: install-macos-apple - .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.8.0/MNE-Python-1.8.0_0-macOS_M1.pkg + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.9.0/MNE-Python-1.9.0_0-macOS_M1.pkg :ref-type: ref :color: primary :shadow: @@ -70,7 +70,7 @@ Platform-specific installers :class-content: text-center :name: install-windows - .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.8.0/MNE-Python-1.8.0_0-Windows.exe + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.9.0/MNE-Python-1.9.0_0-Windows.exe :ref-type: ref :color: primary :shadow: @@ -156,7 +156,7 @@ To remove the MNE-Python distribution provided by our installers above: .. code-block:: bash $ which python - /home/username/mne-python/1.8.0_0/bin/python + /home/username/mne-python/1.9.0_0/bin/python $ rm -Rf /home/$USER/mne-python $ rm /home/$USER/.local/share/applications/mne-python-*.desktop @@ -170,7 +170,7 @@ To remove the MNE-Python distribution provided by our installers above: .. code-block:: bash $ which python - /Users/username/Applications/MNE-Python/1.8.0_0/.mne-python/bin/python + /Users/username/Applications/MNE-Python/1.9.0_0/.mne-python/bin/python $ rm -Rf /Users/$USER/Applications/MNE-Python # if user-specific $ rm -Rf /Applications/MNE-Python # if system-wide diff --git a/doc/sphinxext/prs/13029.json b/doc/sphinxext/prs/13029.json new file mode 100644 index 00000000000..33a84c3f2c6 --- /dev/null +++ b/doc/sphinxext/prs/13029.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "f3a7fde522d69bc5bbc15844718812c7ab6480f4", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12896.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12995.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12996.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12997.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12998.json": { + "a": 131, + "d": 0 + }, + "doc/sphinxext/prs/12999.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13000.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13001.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13003.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13007.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13009.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13010.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13011.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13012.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13015.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13017.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13018.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13019.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13020.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13021.json": { + "a": 59, + "d": 0 + } + } +} \ No newline at end of file diff --git a/doc/sphinxext/prs/13031.json b/doc/sphinxext/prs/13031.json new file mode 100644 index 00000000000..428346e1b90 --- /dev/null +++ b/doc/sphinxext/prs/13031.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5b06ca4bb8f9138bf4af85ea3171d95df07462c5", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 2, + "d": 2 + }, + "doc/documentation/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/prs/13029.json": { + "a": 91, + "d": 0 + }, + "doc/sphinxext/prs/6915.json": { + "a": 43, + "d": 0 + }, + "tools/dev/update_credit_json.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/doc/sphinxext/prs/13032.json b/doc/sphinxext/prs/13032.json new file mode 100644 index 00000000000..041aa7dfe1b --- /dev/null +++ b/doc/sphinxext/prs/13032.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b38385ef90d0fd8214d54b15c5fd91333c3bc032", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/doc/sphinxext/prs/13035.json b/doc/sphinxext/prs/13035.json new file mode 100644 index 00000000000..e9cf38b09c9 --- /dev/null +++ b/doc/sphinxext/prs/13035.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "dcd26258c5fd83fd3974d73ba2b1e2773c33bc3d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/io/ant/ant.py": { + "a": 14, + "d": 12 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 23, + "d": 24 + }, + "mne/utils/tests/test_check.py": { + "a": 7, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 6 + }, + "tutorials/intro/70_report.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/doc/sphinxext/prs/13036.json b/doc/sphinxext/prs/13036.json new file mode 100644 index 00000000000..6ce98904756 --- /dev/null +++ b/doc/sphinxext/prs/13036.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "41dbdd55eaff77314440ebc8700e0e58b1183113", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13036.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 26, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/doc/sphinxext/prs/6915.json b/doc/sphinxext/prs/6915.json new file mode 100644 index 00000000000..24abd2f2a8c --- /dev/null +++ b/doc/sphinxext/prs/6915.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "610ec2a50d7a0e17d1ae8a229793a51370dec81d", + "authors": [ + { + "n": "Fahimeh Mamashli", + "e": "fahimeh.mamashli@pfizer.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/devel/6915.newfeature.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/brainstorm_data.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/stim.py": { + "a": 56, + "d": 9 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 35, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/environment.yml b/environment.yml index 18a8ec931fa..898132bc0a4 100644 --- a/environment.yml +++ b/environment.yml @@ -4,7 +4,7 @@ channels: - conda-forge dependencies: - python >=3.10 - - antio >=0.4.0 + - antio >=0.5.0 - darkdetect - decorator - defusedxml @@ -30,7 +30,7 @@ dependencies: - nilearn - numba - numpy >=1.23,<3 - - openmeeg =2.5.12=*_1 + - openmeeg >=2.5.5 - packaging - pandas - pillow diff --git a/examples/datasets/brainstorm_data.py b/examples/datasets/brainstorm_data.py index 6331c9f1b29..ab5499fea71 100644 --- a/examples/datasets/brainstorm_data.py +++ b/examples/datasets/brainstorm_data.py @@ -6,9 +6,8 @@ ===================================== Here we compute the evoked from raw for the Brainstorm -tutorial dataset. For comparison, see :footcite:`TadelEtAl2011` and: - - https://neuroimage.usc.edu/brainstorm/Tutorials/MedianNerveCtf +tutorial dataset. For comparison, see :footcite:`TadelEtAl2011` and +https://neuroimage.usc.edu/brainstorm/Tutorials/MedianNerveCtf. """ # Authors: Mainak Jas diff --git a/ignore_words.txt b/ignore_words.txt index 150a32058e2..12e1a14ae0e 100644 --- a/ignore_words.txt +++ b/ignore_words.txt @@ -41,3 +41,5 @@ connec sme tim whitelists +gotcha +uner diff --git a/mne/conftest.py b/mne/conftest.py index 5d3e033e095..d18b440dc9c 100644 --- a/mne/conftest.py +++ b/mne/conftest.py @@ -119,7 +119,7 @@ def pytest_configure(config): # we should remove them from here. # - This list should also be considered alongside reset_warnings in # doc/conf.py. - if os.getenv("MNE_IGNORE_WARNINGS_IN_TESTS", "") != "true": + if os.getenv("MNE_IGNORE_WARNINGS_IN_TESTS", "") not in ("true", "1"): first_kind = "error" else: first_kind = "always" @@ -180,6 +180,8 @@ def pytest_configure(config): ignore:The 'copy' argument in Quantity is deprecated.*: # debugpy uses deprecated matplotlib API ignore:The (non_)?interactive_bk attribute was deprecated.*: + # SWIG (via OpenMEEG) + ignore:.*builtin type swigvarlink has no.*:DeprecationWarning """ # noqa: E501 for warning_line in warning_lines.split("\n"): warning_line = warning_line.strip() diff --git a/mne/filter.py b/mne/filter.py index 025f778d07f..ee5b34cd657 100644 --- a/mne/filter.py +++ b/mne/filter.py @@ -434,7 +434,7 @@ def _firwin_design(N, freq, gain, window, sfreq): for this_freq, this_gain in zip(freq[::-1][1:], gain[::-1][1:]): assert this_gain in (0, 1) if this_gain != prev_gain: - # Get the correct N to satistify the requested transition bandwidth + # Get the correct N to satisfy the requested transition bandwidth transition = (prev_freq - this_freq) / 2.0 this_N = int(round(_length_factors[window] / transition)) this_N += 1 - this_N % 2 # make it odd diff --git a/mne/io/ant/ant.py b/mne/io/ant/ant.py index e46aabe8a16..854406267f4 100644 --- a/mne/io/ant/ant.py +++ b/mne/io/ant/ant.py @@ -4,7 +4,6 @@ from __future__ import annotations -import importlib import re from collections import defaultdict from typing import TYPE_CHECKING @@ -16,8 +15,8 @@ from ...annotations import Annotations from ...utils import ( _check_fname, + _soft_import, _validate_type, - check_version, copy_doc, fill_doc, logger, @@ -80,6 +79,8 @@ class RawANT(BaseRaw): Note that the impedance annotation will likely have a duration of ``0``. If the measurement marks a discontinuity, the duration should be modified to cover the discontinuity in its entirety. + encoding : str + Encoding to use for :class:`str` in the CNT file. Defaults to ``'latin-1'``. %(preload)s %(verbose)s """ @@ -93,16 +94,12 @@ def __init__( bipolars: list[str] | tuple[str, ...] | None, impedance_annotation: str, *, + encoding: str = "latin-1", preload: bool | NDArray, verbose=None, ) -> None: logger.info("Reading ANT file %s", fname) - if importlib.util.find_spec("antio") is None: - raise ImportError( - "Missing optional dependency 'antio'. Use pip or conda to install " - "'antio'." - ) - check_version("antio", "0.3.0") + _soft_import("antio", "reading ANT files", min_version="0.5.0") from antio import read_cnt from antio.parser import ( @@ -122,8 +119,7 @@ def __init__( raise ValueError("The impedance annotation cannot be an empty string.") cnt = read_cnt(fname) # parse channels, sampling frequency, and create info - ch_info = read_info(cnt) # load in 2 lines for compat with antio 0.2 and 0.3 - ch_names, ch_units, ch_refs = ch_info[0], ch_info[1], ch_info[2] + ch_names, ch_units, ch_refs, _, _ = read_info(cnt, encoding=encoding) ch_types = _parse_ch_types(ch_names, eog, misc, ch_refs) if bipolars is not None: # handle bipolar channels bipolars_idx = _handle_bipolar_channels(ch_names, ch_refs, bipolars) @@ -139,9 +135,9 @@ def __init__( ch_names, sfreq=cnt.get_sample_frequency(), ch_types=ch_types ) info.set_meas_date(read_meas_date(cnt)) - make, model, serial, site = read_device_info(cnt) + make, model, serial, site = read_device_info(cnt, encoding=encoding) info["device_info"] = dict(type=make, model=model, serial=serial, site=site) - his_id, name, sex, birthday = read_subject_info(cnt) + his_id, name, sex, birthday = read_subject_info(cnt, encoding=encoding) info["subject_info"] = dict( his_id=his_id, first_name=name, @@ -315,6 +311,7 @@ def read_raw_ant( bipolars=None, impedance_annotation="impedance", *, + encoding: str = "latin-1", preload=False, verbose=None, ) -> RawANT: @@ -324,6 +321,10 @@ def read_raw_ant( raw : instance of RawANT A Raw object containing ANT data. See :class:`mne.io.Raw` for documentation of attributes and methods. + + Notes + ----- + .. versionadded:: 1.9 """ return RawANT( fname, @@ -331,6 +332,7 @@ def read_raw_ant( misc=misc, bipolars=bipolars, impedance_annotation=impedance_annotation, + encoding=encoding, preload=preload, verbose=verbose, ) diff --git a/mne/io/ant/tests/test_ant.py b/mne/io/ant/tests/test_ant.py index e51c40cfde6..8c8530d400d 100644 --- a/mne/io/ant/tests/test_ant.py +++ b/mne/io/ant/tests/test_ant.py @@ -17,7 +17,7 @@ from mne.io import BaseRaw, read_raw, read_raw_ant, read_raw_brainvision from mne.io.ant.ant import RawANT -pytest.importorskip("antio", minversion="0.4.0") +pytest.importorskip("antio", minversion="0.5.0") data_path = testing.data_path(download=False) / "antio" diff --git a/mne/preprocessing/_annotate_amplitude.py b/mne/preprocessing/_annotate_amplitude.py index 943c20c0ba2..0cd5676e703 100644 --- a/mne/preprocessing/_annotate_amplitude.py +++ b/mne/preprocessing/_annotate_amplitude.py @@ -126,7 +126,7 @@ def annotate_amplitude( for ch_type, picks_of_type in _picks_by_type(raw.info, exclude="bads") if np.intersect1d(picks_of_type, picks_, assume_unique=True).size != 0 } - del picks_ # re-using this variable name in for loop + del picks_ # reusing this variable name in for loop # skip BAD_acq_skip sections onsets, ends = _annotations_starts_stops(raw, "bad_acq_skip", invert=True) diff --git a/mne/preprocessing/stim.py b/mne/preprocessing/stim.py index 7db1bab4c85..a823820988b 100644 --- a/mne/preprocessing/stim.py +++ b/mne/preprocessing/stim.py @@ -11,7 +11,7 @@ from ..event import find_events from ..evoked import Evoked from ..io import BaseRaw -from ..utils import _check_option, _check_preload, fill_doc +from ..utils import _check_option, _check_preload, _validate_type, fill_doc def _get_window(start, end): @@ -20,7 +20,9 @@ def _get_window(start, end): return window -def _fix_artifact(data, window, picks, first_samp, last_samp, mode): +def _fix_artifact( + data, window, picks, first_samp, last_samp, base_tmin, base_tmax, mode +): """Modify original data by using parameter data.""" if mode == "linear": x = np.array([first_samp, last_samp]) @@ -32,6 +34,10 @@ def _fix_artifact(data, window, picks, first_samp, last_samp, mode): data[picks, first_samp:last_samp] = ( data[picks, first_samp:last_samp] * window[np.newaxis, :] ) + if mode == "constant": + data[picks, first_samp:last_samp] = data[picks, base_tmin:base_tmax].mean( + axis=1 + )[:, None] @fill_doc @@ -41,6 +47,8 @@ def fix_stim_artifact( event_id=None, tmin=0.0, tmax=0.01, + *, + baseline=None, mode="linear", stim_channel=None, picks=None, @@ -63,10 +71,23 @@ def fix_stim_artifact( Start time of the interpolation window in seconds. tmax : float End time of the interpolation window in seconds. - mode : 'linear' | 'window' + baseline : None | tuple, shape (2,) + The baseline to use when ``mode='constant'``, in which case it + must be non-None. + + .. versionadded:: 1.8 + mode : 'linear' | 'window' | 'constant' Way to fill the artifacted time interval. - 'linear' does linear interpolation - 'window' applies a (1 - hanning) window. + + ``"linear"`` + Does linear interpolation. + ``"window"`` + Applies a ``(1 - hanning)`` window. + ``"constant"`` + Uses baseline average. baseline parameter must be provided. + + .. versionchanged:: 1.8 + Added the ``"constant"`` mode. stim_channel : str | None Stim channel to use. %(picks_all_data)s @@ -76,9 +97,22 @@ def fix_stim_artifact( inst : instance of Raw or Evoked or Epochs Instance with modified data. """ - _check_option("mode", mode, ["linear", "window"]) + _check_option("mode", mode, ["linear", "window", "constant"]) s_start = int(np.ceil(inst.info["sfreq"] * tmin)) s_end = int(np.ceil(inst.info["sfreq"] * tmax)) + if mode == "constant": + _validate_type( + baseline, (tuple, list), "baseline", extra="when mode='constant'" + ) + _check_option("len(baseline)", len(baseline), [2]) + for bi, b in enumerate(baseline): + _validate_type( + b, "numeric", f"baseline[{bi}]", extra="when mode='constant'" + ) + b_start = int(np.ceil(inst.info["sfreq"] * baseline[0])) + b_end = int(np.ceil(inst.info["sfreq"] * baseline[1])) + else: + b_start = b_end = np.nan if (mode == "window") and (s_end - s_start) < 4: raise ValueError( 'Time range is too short. Use a larger interval or set mode to "linear".' @@ -104,7 +138,11 @@ def fix_stim_artifact( for event_idx in event_start: first_samp = int(event_idx) - inst.first_samp + s_start last_samp = int(event_idx) - inst.first_samp + s_end - _fix_artifact(data, window, picks, first_samp, last_samp, mode) + base_t1 = int(event_idx) - inst.first_samp + b_start + base_t2 = int(event_idx) - inst.first_samp + b_end + _fix_artifact( + data, window, picks, first_samp, last_samp, base_t1, base_t2, mode + ) elif isinstance(inst, BaseEpochs): if inst.reject is not None: raise RuntimeError( @@ -114,14 +152,23 @@ def fix_stim_artifact( first_samp = s_start - e_start last_samp = s_end - e_start data = inst._data + base_t1 = b_start - e_start + base_t2 = b_end - e_start for epoch in data: - _fix_artifact(epoch, window, picks, first_samp, last_samp, mode) + _fix_artifact( + epoch, window, picks, first_samp, last_samp, base_t1, base_t2, mode + ) elif isinstance(inst, Evoked): first_samp = s_start - inst.first last_samp = s_end - inst.first data = inst.data - _fix_artifact(data, window, picks, first_samp, last_samp, mode) + base_t1 = b_start - inst.first + base_t2 = b_end - inst.first + + _fix_artifact( + data, window, picks, first_samp, last_samp, base_t1, base_t2, mode + ) else: raise TypeError(f"Not a Raw or Epochs or Evoked (got {type(inst)}).") diff --git a/mne/preprocessing/tests/test_fine_cal.py b/mne/preprocessing/tests/test_fine_cal.py index b25b824bae0..02c596bf4bc 100644 --- a/mne/preprocessing/tests/test_fine_cal.py +++ b/mne/preprocessing/tests/test_fine_cal.py @@ -232,7 +232,7 @@ def test_fine_cal_systems(system, tmp_path): n_ref = 28 corrs = (0.19, 0.41, 0.49) sfs = [0.5, 0.7, 0.9, 1.5] - corr_tol = 0.45 + corr_tol = 0.55 elif system == "fil": raw = read_raw_fil(fil_fname, verbose="error") raw.info["bads"] = [f"G2-{a}-{b}" for a in ("MW", "DS", "DT") for b in "YZ"] diff --git a/mne/preprocessing/tests/test_stim.py b/mne/preprocessing/tests/test_stim.py index 7ae1c4418b4..2d463a4af5a 100644 --- a/mne/preprocessing/tests/test_stim.py +++ b/mne/preprocessing/tests/test_stim.py @@ -55,6 +55,18 @@ def test_fix_stim_artifact(): data_from_epochs_fix = epochs.get_data(copy=False)[:, :, tmin_samp:tmax_samp] assert not np.all(data_from_epochs_fix != 0) + baseline = (-0.1, -0.05) + epochs = fix_stim_artifact( + epochs, tmin=tmin, tmax=tmax, baseline=baseline, mode="constant" + ) + b_start = int(np.ceil(epochs.info["sfreq"] * baseline[0])) + b_end = int(np.ceil(epochs.info["sfreq"] * baseline[1])) + base_t1 = b_start - e_start + base_t2 = b_end - e_start + baseline_mean = epochs.get_data()[:, :, base_t1:base_t2].mean(axis=2)[0][0] + data = epochs.get_data()[:, :, tmin_samp:tmax_samp] + assert data[0][0][0] == baseline_mean + # use window before stimulus in raw event_idx = np.where(events[:, 2] == 1)[0][0] tmin, tmax = -0.045, -0.015 @@ -81,8 +93,22 @@ def test_fix_stim_artifact(): raw, events, event_id=1, tmin=tmin, tmax=tmax, mode="window" ) data, times = raw[:, (tidx + tmin_samp) : (tidx + tmax_samp)] + assert np.all(data) == 0.0 + raw = fix_stim_artifact( + raw, + events, + event_id=1, + tmin=tmin, + tmax=tmax, + baseline=baseline, + mode="constant", + ) + data, times = raw[:, (tidx + tmin_samp) : (tidx + tmax_samp)] + baseline_mean, _ = raw[:, (tidx + b_start) : (tidx + b_end)] + assert baseline_mean.mean(axis=1)[0] == data[0][0] + # get epochs from raw with fixed data tmin, tmax, event_id = -0.2, 0.5, 1 epochs = Epochs( @@ -117,3 +143,12 @@ def test_fix_stim_artifact(): evoked = fix_stim_artifact(evoked, tmin=tmin, tmax=tmax, mode="window") data = evoked.data[:, tmin_samp:tmax_samp] assert np.all(data) == 0.0 + + evoked = fix_stim_artifact( + evoked, tmin=tmin, tmax=tmax, baseline=baseline, mode="constant" + ) + base_t1 = int(baseline[0] * evoked.info["sfreq"]) - evoked.first + base_t2 = int(baseline[1] * evoked.info["sfreq"]) - evoked.first + data = evoked.data[:, tmin_samp:tmax_samp] + baseline_mean = evoked.data[:, base_t1:base_t2].mean(axis=1)[0] + assert data[0][0] == baseline_mean diff --git a/mne/time_frequency/tests/test_spectrum.py b/mne/time_frequency/tests/test_spectrum.py index 840aab3bcbd..2f612357e70 100644 --- a/mne/time_frequency/tests/test_spectrum.py +++ b/mne/time_frequency/tests/test_spectrum.py @@ -627,3 +627,29 @@ def test_plot_spectrum_array_with_bads(): spectrum.get_data(exclude=()), spectrum.info, spectrum.freqs ) spectrum2.plot(spatial_colors=False) + + +@pytest.mark.parametrize("dB", (False, True)) +@pytest.mark.parametrize("amplitude", (False, True)) +def test_plot_spectrum_dB(raw_spectrum, dB, amplitude): + """Test that we properly handle amplitude/power and dB.""" + idx = 7 + power = 3 + freqs = np.linspace(1, 100, 100) + data = np.full((1, freqs.size), np.finfo(float).tiny) + data[0, idx] = power + info = create_info(ch_names=["delta"], sfreq=1000, ch_types="eeg") + psd = SpectrumArray(data=data, info=info, freqs=freqs) + with pytest.warns(RuntimeWarning, match="Channel locations not available"): + fig = psd.plot(dB=dB, amplitude=amplitude) + trace = list( + filter(lambda x: len(x.get_data()[0]) == len(freqs), fig.axes[0].lines) + )[0] + got = trace.get_data()[1][idx] + want = power * 1e12 # scaling for EEG (V → μV), squared + if amplitude: + want = np.sqrt(want) + if dB: + want = (20 if amplitude else 10) * np.log10(want) + + assert want == got, f"expected {want}, got {got}" diff --git a/mne/utils/check.py b/mne/utils/check.py index 973fa33fe79..21360df9c83 100644 --- a/mne/utils/check.py +++ b/mne/utils/check.py @@ -385,7 +385,7 @@ def _check_compensation_grade(info1, info2, name1, name2="data", ch_names=None): ) -def _soft_import(name, purpose, strict=True): +def _soft_import(name, purpose, strict=True, *, min_version=None): """Import soft dependencies, providing informative errors on failure. Parameters @@ -398,11 +398,6 @@ def _soft_import(name, purpose, strict=True): strict : bool Whether to raise an error if module import fails. """ - - # so that error msg lines are aligned - def indent(x): - return x.rjust(len(x) + 14) - # Mapping import namespaces to their pypi package name pip_name = dict( sklearn="scikit-learn", @@ -415,27 +410,31 @@ def indent(x): pyvista="pyvistaqt", ).get(name, name) + got_version = None try: mod = import_module(name) - return mod except (ImportError, ModuleNotFoundError): - if strict: - raise RuntimeError( - f"For {purpose} to work, the {name} module is needed, " - + "but it could not be imported.\n" - + "\n".join( - ( - indent( - "use the following installation method " - "appropriate for your environment:" - ), - indent(f"'pip install {pip_name}'"), - indent(f"'conda install -c conda-forge {pip_name}'"), - ) - ) - ) - else: - return False + mod = False + else: + have, got_version = check_version( + name, + min_version=min_version, + return_version=True, + ) + if not have: + mod = False + if mod is False and strict: + extra = "" if min_version is None else f">={min_version}" + if got_version is not None: + extra += f" (found version {got_version})" + raise RuntimeError( + f"For {purpose} to work, the module {name}{extra} is needed, " + "but it could not be imported. Use the following installation method " + "appropriate for your environment:\n\n" + f" pip install {pip_name}\n" + f" conda install -c conda-forge {pip_name}" + ) + return mod def _check_pandas_installed(strict=True): diff --git a/mne/utils/tests/test_check.py b/mne/utils/tests/test_check.py index 4b519198e39..2cfea767aa8 100644 --- a/mne/utils/tests/test_check.py +++ b/mne/utils/tests/test_check.py @@ -28,6 +28,7 @@ _path_like, _record_warnings, _safe_input, + _soft_import, _suggest, _validate_type, catch_logging, @@ -372,3 +373,9 @@ def test_check_sphere_verbose(): _check_sphere("auto", info) with mne.use_log_level("error"): _check_sphere("auto", info) + + +def test_soft_import(): + """Test _soft_import.""" + with pytest.raises(RuntimeError, match=r".* the module mne>=999 \(found version.*"): + _soft_import("mne", "testing", min_version="999") diff --git a/mne/utils/tests/test_docs.py b/mne/utils/tests/test_docs.py index 253317af760..ea355820f57 100644 --- a/mne/utils/tests/test_docs.py +++ b/mne/utils/tests/test_docs.py @@ -122,7 +122,7 @@ def m1(): def test_copy_function_doc_to_method_doc(): - """Test decorator for re-using function docstring as method docstrings.""" + """Test decorator for reusing function docstring as method docstrings.""" def f1(obj, a, b, c): """Docstring for f1. diff --git a/mne/viz/circle.py b/mne/viz/circle.py index fdcbd5a26bb..67a47c0d5fd 100644 --- a/mne/viz/circle.py +++ b/mne/viz/circle.py @@ -6,6 +6,7 @@ from functools import partial from itertools import cycle +from types import SimpleNamespace import numpy as np @@ -371,6 +372,7 @@ def _plot_connectivity_circle( cb_yticks = plt.getp(cb.ax.axes, "yticklabels") cb.ax.tick_params(labelsize=fontsize_colorbar) plt.setp(cb_yticks, color=textcolor) + fig.mne = SimpleNamespace(colorbar=cb) # Add callback for interaction if interactive: diff --git a/mne/viz/tests/test_circle.py b/mne/viz/tests/test_circle.py index a26379f6ccc..c5f3719746b 100644 --- a/mne/viz/tests/test_circle.py +++ b/mne/viz/tests/test_circle.py @@ -17,7 +17,10 @@ def test_plot_channel_labels_circle(): fig, axes = plot_channel_labels_circle( dict(brain=["big", "great", "smart"]), colors=dict(big="r", great="y", smart="b"), + colorbar=True, ) + # check that colorbar handle is returned + assert isinstance(fig.mne.colorbar, matplotlib.colorbar.Colorbar) texts = [ child.get_text() for child in axes.get_children() diff --git a/mne/viz/utils.py b/mne/viz/utils.py index 675b89b2852..00458bf3908 100644 --- a/mne/viz/utils.py +++ b/mne/viz/utils.py @@ -2390,14 +2390,16 @@ def _convert_psds( np.sqrt(psds, out=psds) psds *= scaling ylabel = rf"$\mathrm{{{unit}/\sqrt{{Hz}}}}$" + coef = 20 else: psds *= scaling * scaling if "/" in unit: unit = f"({unit})" ylabel = rf"$\mathrm{{{unit}²/Hz}}$" + coef = 10 if dB: np.log10(np.maximum(psds, np.finfo(float).tiny), out=psds) - psds *= 10 + psds *= coef ylabel = r"$\mathrm{dB}\ $" + ylabel ylabel = "Power (" + ylabel if estimate == "power" else "Amplitude (" + ylabel ylabel += ")" diff --git a/pyproject.toml b/pyproject.toml index 4199e8cd8e0..363844769f6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -88,7 +88,7 @@ full = ["mne[full-no-qt]", "PyQt6 != 6.6.0", "PyQt6-Qt6 != 6.6.0, != 6.7.0"] # We also offter two more variants: mne[full-qt6] (which is equivalent to mne[full]), # and mne[full-pyside6], which will install PySide6 instead of PyQt6. full-no-qt = [ - "antio >= 0.4.0", + "antio >= 0.5.0", "darkdetect", "defusedxml", "dipy", diff --git a/tools/azure_dependencies.sh b/tools/azure_dependencies.sh index 17b5381d72f..56ec04b490d 100755 --- a/tools/azure_dependencies.sh +++ b/tools/azure_dependencies.sh @@ -5,7 +5,7 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) STD_ARGS="--progress-bar off --upgrade" python -m pip install $STD_ARGS pip setuptools wheel if [ "${TEST_MODE}" == "pip" ]; then - python -m pip install $STD_ARGS --only-binary="numba,llvmlite,numpy,scipy,vtk,dipy,openmeeg" -e .[test,full] "openmeeg==2.5.12" + python -m pip install $STD_ARGS --only-binary="numba,llvmlite,numpy,scipy,vtk,dipy,openmeeg" -e .[test,full] elif [ "${TEST_MODE}" == "pip-pre" ]; then ${SCRIPT_DIR}/install_pre_requirements.sh python -m pip install $STD_ARGS --pre -e .[test_extra] diff --git a/tools/circleci_dependencies.sh b/tools/circleci_dependencies.sh index 9c32b008a28..2ecc9718ab2 100755 --- a/tools/circleci_dependencies.sh +++ b/tools/circleci_dependencies.sh @@ -1,12 +1,6 @@ #!/bin/bash -ef python -m pip install --upgrade "pip!=20.3.0" build -# This can be removed once dipy > 1.9.0 is released -python -m pip install --upgrade --progress-bar off \ - numpy scipy h5py -python -m pip install --pre --progress-bar off \ - --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" \ - "dipy>1.9" python -m pip install --upgrade --progress-bar off \ --only-binary "numpy,dipy,scipy,matplotlib,pandas,statsmodels" \ -ve .[full,test,doc] "numpy>=2" \ diff --git a/tools/dev/update_credit_json.py b/tools/dev/update_credit_json.py index e131fd3f33c..de96c040604 100644 --- a/tools/dev/update_credit_json.py +++ b/tools/dev/update_credit_json.py @@ -20,7 +20,9 @@ g = Github(auth=auth, per_page=100) out_path = Path(__file__).parents[2] / "doc" / "sphinxext" / "prs" out_path.mkdir(exist_ok=True) -oldest_pr = 6915 # can update this when the oldest open PR changes to speed things up +# manually update this when the oldest open PR changes to speed things up +# (don't need to look any farther back than this) +oldest_pr = 9176 # JSON formatting json_kwargs = dict(indent=2, ensure_ascii=False, sort_keys=False) diff --git a/tools/hooks/update_environment_file.py b/tools/hooks/update_environment_file.py index bfedca39d1a..78df3eb5f9c 100755 --- a/tools/hooks/update_environment_file.py +++ b/tools/hooks/update_environment_file.py @@ -56,9 +56,6 @@ def split_dep(dep): # `environment.yaml` breaks the solver if package_name == "PySide6": version_spec = version_spec.replace("!=6.7.0,", "") - # openmeeg 2.5.12=*_2 is broken, so pin to 2.5.12=*_1 - if package_name == "openmeeg": - version_spec = "=2.5.12=*_1" # rstrip output line in case `version_spec` == "" line = f" - {package_name} {version_spec}".rstrip() # use pip for packages needing e.g. `platform_system` or `python_version` triaging diff --git a/tools/install_pre_requirements.sh b/tools/install_pre_requirements.sh index 4f9f0165fe2..74868b0a435 100755 --- a/tools/install_pre_requirements.sh +++ b/tools/install_pre_requirements.sh @@ -15,15 +15,21 @@ echo "PyQt6 and scientific-python-nightly-wheels dependencies" python -m pip install $STD_ARGS pip setuptools packaging \ threadpoolctl cycler fonttools kiwisolver pyparsing pillow python-dateutil \ patsy pytz tzdata nibabel tqdm trx-python joblib numexpr "$QT_BINDING" \ - py-cpuinfo blosc2 + py-cpuinfo blosc2 hatchling echo "NumPy/SciPy/pandas etc." python -m pip uninstall -yq numpy python -m pip install $STD_ARGS --only-binary ":all:" --default-timeout=60 \ --index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" \ "numpy>=2.1.0.dev0" "scikit-learn>=1.6.dev0" "scipy>=1.15.0.dev0" \ - "statsmodels>=0.15.0.dev0" "pandas>=3.0.0.dev0" "matplotlib>=3.10.0.dev0" \ + "pandas>=3.0.0.dev0" "matplotlib>=3.10.0.dev0" \ "h5py>=3.12.1" "dipy>=1.10.0.dev0" "pyarrow>=19.0.0.dev0" "tables>=3.10.2.dev0" +# statsmodels requires formulaic@main so we need to use --extra-index-url +echo "statsmodels" +python -m pip install $STD_ARGS --only-binary ":all:" \ + --extra-index-url "https://pypi.anaconda.org/scientific-python-nightly-wheels/simple" \ + "statsmodels>=0.15.0.dev0" + # No Numba because it forces an old NumPy version echo "pymatreader" diff --git a/tutorials/intro/70_report.py b/tutorials/intro/70_report.py index d23bd54aebf..cc32d02679b 100644 --- a/tutorials/intro/70_report.py +++ b/tutorials/intro/70_report.py @@ -7,11 +7,10 @@ :class:`mne.Report` is a way to create interactive HTML summaries of your data. These reports can show many different visualizations for one or multiple participants. -A common use case is creating diagnostic summaries to check data -quality at different stages in the processing pipeline. The report can show -things like plots of data before and after each preprocessing step, epoch -rejection statistics, MRI slices with overlaid BEM shells, all the way up to -plots of estimated cortical activity. +A common use case is creating diagnostic summaries to check data quality at different +stages in the processing pipeline. The report can show things like plots of data before +and after each preprocessing step, epoch rejection statistics, MRI slices with overlaid +BEM shells, all the way up to plots of estimated cortical activity. Compared to a Jupyter notebook, :class:`mne.Report` is easier to deploy, as the HTML pages it generates are self-contained and do not require a running Python diff --git a/tutorials/preprocessing/45_projectors_background.py b/tutorials/preprocessing/45_projectors_background.py index 128229e516a..3c83d49d8c3 100644 --- a/tutorials/preprocessing/45_projectors_background.py +++ b/tutorials/preprocessing/45_projectors_background.py @@ -488,7 +488,7 @@ def setup_3d_axes(): # for this recommendation: # # 1. It is computationally cheaper to apply projectors to data *after* the -# data have been reducted to just the segments of interest (the epochs) +# data have been reduced to just the segments of interest (the epochs) # # 2. If you are applying amplitude-based rejection criteria to epochs, it is # preferable to reject based on the signal *after* projectors have been diff --git a/tutorials/time-freq/50_ssvep.py b/tutorials/time-freq/50_ssvep.py index a0d130f1d35..a625a001d9e 100644 --- a/tutorials/time-freq/50_ssvep.py +++ b/tutorials/time-freq/50_ssvep.py @@ -641,7 +641,7 @@ def snr_spectrum(psd, noise_n_neighbor_freqs=1, noise_skip_neighbor_freqs=1): ].mean(axis=1) fig, ax = plt.subplots(1) -ax.boxplot(window_snrs, tick_labels=window_lengths, vert=True) +ax.boxplot(window_snrs, tick_labels=window_lengths, orientation="vertical") ax.set( title="Effect of trial duration on 12 Hz SNR", ylabel="Average SNR",