Skip to content

Commit 7ce45c5

Browse files
authored
Merge branch 'main' into exclude_bads_consistent_handling
2 parents f51f7e0 + a0eb925 commit 7ce45c5

72 files changed

Lines changed: 4880 additions & 575 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.circleci/config.yml

Lines changed: 104 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ jobs:
100100
name: Set BASH_ENV
101101
command: ./tools/circleci_bash_env.sh
102102

103+
# Writes testing_version.txt and misc_version.txt, used in the cache keys of
104+
# the two datasets whose versions actually change on a regular basis. Caches
105+
# are immutable on CircleCI, so a dataset with a fixed key would be pinned to
106+
# whatever was first cached and re-downloaded in full on every later run.
107+
- run:
108+
name: Get dataset versions
109+
command: ./tools/get_testing_version.sh
110+
103111
- run:
104112
name: Install fonts needed for diagrams
105113
command: |
@@ -110,13 +118,15 @@ jobs:
110118
curl https://codeload.github.com/adobe-fonts/source-sans/tar.gz/3.028R | tar xz -C $HOME/.fonts
111119
fc-cache -f
112120
113-
# Load uv cache
114-
- restore_cache:
115-
keys:
116-
- uv-cache-0
121+
# Load uv cache. Caches are immutable on CircleCI, so a fixed key would freeze
122+
# the cache at whatever the dependencies looked like the first time it was
123+
# written; keying on pyproject.toml refreshes it when the dependencies change,
124+
# and the prefix-only fallback still gets a warm (if slightly stale) cache in
125+
# between.
117126
- restore_cache:
118127
keys:
119-
- user-install-bin-cache-311
128+
- uv-cache-1-{{ checksum "pyproject.toml" }}
129+
- uv-cache-1-
120130

121131
# Hack in uninstalls of libraries as necessary if pip doesn't do the right thing in upgrading for us...
122132
- run:
@@ -125,14 +135,9 @@ jobs:
125135
./tools/circleci_dependencies.sh
126136
127137
- save_cache:
128-
key: uv-cache-0
138+
key: uv-cache-1-{{ checksum "pyproject.toml" }}
129139
paths:
130140
- ~/.cache/uv
131-
- save_cache:
132-
key: user-install-bin-cache-311
133-
paths:
134-
- ~/.local/lib/python3.11/site-packages
135-
- ~/.local/bin
136141

137142
- run:
138143
name: Check Qt
@@ -142,7 +147,7 @@ jobs:
142147
# Load tiny cache so that ~/.mne does not need to be created below
143148
- restore_cache:
144149
keys:
145-
- data-cache-tiny-0
150+
- data-cache-tiny-0-{{ checksum "misc_version.txt" }}
146151

147152
# Look at what we have and fail early if there is some library conflict
148153
- run:
@@ -211,7 +216,7 @@ jobs:
211216
- data-cache-spm-face
212217
- restore_cache:
213218
keys:
214-
- data-cache-testing
219+
- data-cache-testing-{{ checksum "testing_version.txt" }}
215220
- restore_cache:
216221
keys:
217222
- data-cache-visual-1
@@ -239,87 +244,12 @@ jobs:
239244
echo "BUILD=$(cat build.txt)"
240245
ls -al ~/mne_data;
241246
242-
# Run doctest (if it's full or front) before building the docs
243-
- run:
244-
name: make test-doc
245-
command: |
246-
if [[ $(cat gitlog.txt) == *"[circle front]"* ]] || [[ $(cat build.txt) == "html-memory" ]] ; then
247-
make test-doc;
248-
mkdir -p doc/_build/test-results/test-doc;
249-
cp junit-results.xml doc/_build/test-results/test-doc/junit.xml;
250-
cp coverage.xml doc/_build/test-results/test-doc/coverage.xml;
251-
fi;
252-
# Build docs
253-
- run:
254-
name: make html
255-
command: | # we have -o pipefail in #BASH_ENV so we should be okay
256-
set -x
257-
PATTERN=$(cat pattern.txt) make -C doc $(cat build.txt) 2>&1 | tee sphinx_log.txt
258-
- run:
259-
name: Check sphinx log for warnings (which are treated as errors)
260-
when: always
261-
command: |
262-
! grep "^.*\(WARNING\|ERROR\): " sphinx_log.txt
263-
- run:
264-
name: Show profiling output
265-
when: always
266-
command: |
267-
if compgen -G "doc/*.dat" > /dev/null; then
268-
mkdir -p doc/generated
269-
mprof plot doc/*.dat --output doc/generated/memory.png
270-
else
271-
echo "No profile data found in doc/"
272-
fi
273-
- run:
274-
name: Sanity check system state
275-
command: |
276-
python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)"
277-
278-
# Reduce upload time of artifacts we will (almost) never look at
279-
- run:
280-
name: Reduce artifact upload time
281-
command: |
282-
if grep -q html-pattern-memory build.txt; then
283-
zip -rm doc/_build/html/_downloads.zip doc/_build/html/_downloads
284-
fi
285-
for NAME in generated auto_tutorials auto_examples; do
286-
zip -rm doc/${NAME}.zip doc/${NAME}
287-
done
288-
289-
# Save the JUnit file
290-
- store_test_results:
291-
path: doc/_build/test-results
292-
- store_artifacts:
293-
path: doc/_build/test-results
294-
destination: test-results
295-
# Upload test results to Codecov
296-
- run:
297-
name: Upload test results to Codecov
298-
environment:
299-
CODECOV_TOKEN: fb4c4a94-72d7-4743-bb08-af25b623a29a
300-
command: |
301-
if [[ -f doc/_build/test-results/test-doc/coverage.xml ]]; then
302-
bash <(curl -s https://codecov.io/bash) -f doc/_build/test-results/test-doc/coverage.xml || true
303-
fi
304-
# Save the SG RST
305-
- store_artifacts:
306-
path: doc/auto_examples.zip
307-
- store_artifacts:
308-
path: doc/auto_tutorials.zip
309-
- store_artifacts:
310-
path: doc/generated.zip
311-
# Save the HTML
312-
- store_artifacts:
313-
path: doc/_build/html/
314-
destination: html
315-
- persist_to_workspace:
316-
root: doc/_build
317-
paths:
318-
- html
319-
320-
# Keep these separate, maybe better in terms of size limitations (?)
247+
# Saved here rather than at the end of the job: everything above has
248+
# finished downloading, and a failure in the (long, flaky) doc build below
249+
# should not throw the downloads away. Kept as separate caches, maybe
250+
# better in terms of size limitations (?)
321251
- save_cache:
322-
key: data-cache-tiny-0 # < 100 M, might as well combine
252+
key: data-cache-tiny-0-{{ checksum "misc_version.txt" }} # < 100 M, might as well combine
323253
paths:
324254
- ~/.mne
325255
- ~/mne_data/MNE-kiloword-data # (28 M)
@@ -394,7 +324,7 @@ jobs:
394324
paths:
395325
- ~/mne_data/MNE-spm-face # (1.5 G)
396326
- save_cache:
397-
key: data-cache-testing
327+
key: data-cache-testing-{{ checksum "testing_version.txt" }}
398328
paths:
399329
- ~/mne_data/MNE-testing-data # (2.5 G)
400330
- save_cache:
@@ -414,6 +344,84 @@ jobs:
414344
paths:
415345
- ~/mne_data/ds004388 # (1.8 G)
416346

347+
# Run doctest (if it's full or front) before building the docs
348+
- run:
349+
name: make test-doc
350+
command: |
351+
if [[ $(cat gitlog.txt) == *"[circle front]"* ]] || [[ $(cat build.txt) == "html-memory" ]] ; then
352+
make test-doc;
353+
mkdir -p doc/_build/test-results/test-doc;
354+
cp junit-results.xml doc/_build/test-results/test-doc/junit.xml;
355+
cp coverage.xml doc/_build/test-results/test-doc/coverage.xml;
356+
fi;
357+
# Build docs
358+
- run:
359+
name: make html
360+
command: | # we have -o pipefail in #BASH_ENV so we should be okay
361+
set -x
362+
PATTERN=$(cat pattern.txt) make -C doc $(cat build.txt) 2>&1 | tee sphinx_log.txt
363+
- run:
364+
name: Check sphinx log for warnings (which are treated as errors)
365+
when: always
366+
command: |
367+
! grep "^.*\(WARNING\|ERROR\): " sphinx_log.txt
368+
- run:
369+
name: Show profiling output
370+
when: always
371+
command: |
372+
if compgen -G "doc/*.dat" > /dev/null; then
373+
mkdir -p doc/generated
374+
mprof plot doc/*.dat --output doc/generated/memory.png
375+
else
376+
echo "No profile data found in doc/"
377+
fi
378+
- run:
379+
name: Sanity check system state
380+
command: |
381+
python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)"
382+
383+
# Reduce upload time of artifacts we will (almost) never look at
384+
- run:
385+
name: Reduce artifact upload time
386+
command: |
387+
if grep -q html-pattern-memory build.txt; then
388+
zip -rm doc/_build/html/_downloads.zip doc/_build/html/_downloads
389+
fi
390+
for NAME in generated auto_tutorials auto_examples; do
391+
zip -rm doc/${NAME}.zip doc/${NAME}
392+
done
393+
394+
# Save the JUnit file
395+
- store_test_results:
396+
path: doc/_build/test-results
397+
- store_artifacts:
398+
path: doc/_build/test-results
399+
destination: test-results
400+
# Upload test results to Codecov
401+
- run:
402+
name: Upload test results to Codecov
403+
environment:
404+
CODECOV_TOKEN: fb4c4a94-72d7-4743-bb08-af25b623a29a
405+
command: |
406+
if [[ -f doc/_build/test-results/test-doc/coverage.xml ]]; then
407+
bash <(curl -s https://codecov.io/bash) -f doc/_build/test-results/test-doc/coverage.xml || true
408+
fi
409+
# Save the SG RST
410+
- store_artifacts:
411+
path: doc/auto_examples.zip
412+
- store_artifacts:
413+
path: doc/auto_tutorials.zip
414+
- store_artifacts:
415+
path: doc/generated.zip
416+
# Save the HTML
417+
- store_artifacts:
418+
path: doc/_build/html/
419+
destination: html
420+
- persist_to_workspace:
421+
root: doc/_build
422+
paths:
423+
- html
424+
417425

418426
linkcheck:
419427
# there are a few files excluded from this for expediency, see Makefile
@@ -442,7 +450,8 @@ jobs:
442450
command: ./tools/circleci_bash_env.sh
443451
- restore_cache:
444452
keys:
445-
- uv-cache-0
453+
- uv-cache-1-{{ checksum "pyproject.toml" }}
454+
- uv-cache-1-
446455
- run:
447456
name: Get Python running
448457
command: |

.github/workflows/tests.yml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,12 @@ jobs:
136136
project-root: ${{ github.workspace }}
137137
groups: lockfile_extras
138138
if: matrix.kind == 'old'
139-
# Minimal commands on Linux (macOS stalls)
140-
- uses: actions/cache@v6.1.0
141-
with:
142-
key: minimal-commands-1
143-
path: ~/minimal_cmds
144-
if: startswith(matrix.os, 'ubuntu') && matrix.kind != 'minimal' && matrix.kind != 'old' && matrix.kind != 'pip-ft'
145-
- run: bash ./tools/get_minimal_commands.sh
146-
if: startswith(matrix.os, 'ubuntu') && matrix.kind != 'minimal' && matrix.kind != 'old' && matrix.kind != 'pip-ft'
139+
# MNE-C minimal commands. The action caches the download and no-ops on
140+
# platforms that have no binaries (macOS arm64, Windows, Linux arm64), so it
141+
# only needs to be gated on the kinds that deliberately do without them.
142+
- name: Setup minimal commands
143+
uses: mne-tools/mne-tools/actions/setup-minimal-commands@main
144+
if: matrix.kind != 'minimal' && matrix.kind != 'old' && matrix.kind != 'pip-ft'
147145
- run: bash ./tools/github_actions_infos.sh
148146
- name: Check Qt import
149147
uses: mne-tools/mne-tools/actions/check-qt-import@main
@@ -156,7 +154,7 @@ jobs:
156154
- run: ./tools/get_testing_version.sh
157155
- uses: actions/cache@v6.1.0
158156
with:
159-
key: ${{ env.TESTING_VERSION }}
157+
key: mne_data-testing-${{ env.TESTING_VERSION }}-misc-${{ env.MISC_VERSION }}
160158
path: ~/mne_data
161159
- run: bash ./tools/github_actions_download.sh
162160
- run: bash ./tools/github_actions_test.sh # for some reason on macOS we need to run "bash X" in order for a failed test run to show up

.gitignore

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,13 @@ venv/
104104
.hypothesis/
105105
.ruff_cache/
106106
.ipynb_checkpoints/
107-
/.claude/
107+
/.claude/
108+
uv.lock
109+
110+
# written into the repo root by the CI helper scripts in tools/
111+
/build.txt
112+
/gitlog.txt
113+
/merge.txt
114+
/misc_version.txt
115+
/pattern.txt
116+
/testing_version.txt

azure-pipelines.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ stages:
5959
key: minimal-cmds-1
6060
path: /home/vsts/minimal_cmds
6161
displayName: Cache minimal commands
62-
- bash: ./tools/get_minimal_commands.sh
62+
- bash: $(MNE_TOOLS_DIR)/tools/get_minimal_commands.sh
6363
displayName: Get minimal commands
6464
- task: UsePythonVersion@0
6565
inputs:
@@ -82,7 +82,7 @@ stages:
8282
displayName: Get testing version
8383
- task: Cache@2
8484
inputs:
85-
key: $(testing_version)
85+
key: mne_data-testing-$(testing_version)-misc-$(misc_version)
8686
path: /home/vsts/mne_data
8787
displayName: Cache testing data
8888
- bash: ./tools/github_actions_download.sh
@@ -133,7 +133,7 @@ stages:
133133
displayName: Get testing version
134134
- task: Cache@2
135135
inputs:
136-
key: $(testing_version)
136+
key: mne_data-testing-$(testing_version)-misc-$(misc_version)
137137
path: /home/vsts/mne_data
138138
displayName: Cache testing data
139139
- bash: ./tools/github_actions_download.sh
@@ -211,7 +211,7 @@ stages:
211211
displayName: Get testing version
212212
- task: Cache@2
213213
inputs:
214-
key: $(testing_version)
214+
key: mne_data-testing-$(testing_version)-misc-$(misc_version)
215215
path: C:\Users\VssAdministrator\mne_data
216216
displayName: Cache testing data
217217
- bash: ./tools/github_actions_download.sh

doc/api/datasets.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,6 @@ Datasets
4848
refmeg_noise.data_path
4949
ssvep.data_path
5050
erp_core.data_path
51+
erp_core.fetch_file
5152
epilepsy_ecog.data_path
5253
eyelink.data_path

doc/api/inverse.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ Inverse Solutions
8585
Dipole
8686
DipoleFixed
8787
fit_dipole
88+
gui.dipolefit
8889

8990
:py:mod:`mne.dipole`:
9091

doc/api/statistics.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,12 @@ Compute ``adjacency`` matrices for cluster-level statistics:
6868

6969
channels.find_ch_adjacency
7070
channels.read_ch_adjacency
71+
label_adjacency
7172
spatial_dist_adjacency
7273
spatial_src_adjacency
7374
spatial_tris_adjacency
7475
spatial_inter_hemi_adjacency
7576
spatio_temporal_src_adjacency
7677
spatio_temporal_tris_adjacency
7778
spatio_temporal_dist_adjacency
79+
volume_label_adjacency
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a GUI for interactive guided dipole fitting (:func:`mne.gui.dipolefit`), by `Marijn van Vliet`_

doc/changes/dev/13795.other.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Made :meth:`evoked.plot() <mne.Evoked.plot>` instantiate ``MNELineFigure`` when it creates its own figure, aligning this path with the ongoing 2D plotting figure-class refactor discussed in :gh:`7751`, by `Pragnya Khandelwal`_.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Added :ref:`tut-gal-decoding`, a tutorial on Generalization Across Location
2+
(GAL) and Time-GAL decoding of EEG data, by `Bruno Aristimunha`_ and
3+
:newcontrib:`Alejandro Santos Mayo`.

0 commit comments

Comments
 (0)