Skip to content

Commit

Permalink
Merge branch 'main' into sklearn
Browse files Browse the repository at this point in the history
  • Loading branch information
larsoner authored Jan 17, 2025
2 parents 1918de3 + bd8c318 commit 98a0891
Show file tree
Hide file tree
Showing 108 changed files with 340 additions and 363 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
repos:
# Ruff mne
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6
rev: v0.9.1
hooks:
- id: ruff
name: ruff lint mne
Expand Down Expand Up @@ -82,7 +82,7 @@ repos:

# zizmor
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.0.0
rev: v1.1.1
hooks:
- id: zizmor

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ stages:
- bash: |
set -e
python -m pip install --progress-bar off --upgrade pip
python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git@main" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1" pandas neo pymatreader antio defusedxml
python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git@main" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1,!=6.8.1.1" pandas neo pymatreader antio defusedxml
python -m pip uninstall -yq mne
python -m pip install --progress-bar off --upgrade -e .[test]
displayName: 'Install dependencies with pip'
Expand Down
1 change: 1 addition & 0 deletions doc/changes/devel/13063.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug in the colorbars created by :func:`mne.viz.plot_evoked_topomap` by `Santeri Ruuskanen`_.
1 change: 1 addition & 0 deletions doc/changes/devel/13069.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug cause by unnecessary assertion when loading mixed frequency EDFs without preloading :func:`mne.io.read_raw_edf` by `Simon Kern`_.
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ def fix_sklearn_inherited_docstrings(app, what, name, obj, options, lines):
rst_prolog += f"""
.. |{icon}| raw:: html
<i class="{' '.join(classes + (f'fa-{icon}',))}"></i>
<i class="{" ".join(classes + (f"fa-{icon}",))}"></i>
"""

rst_prolog += """
Expand Down
8 changes: 4 additions & 4 deletions doc/sphinxext/credit_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ def generate_credit_rst(app=None, *, verbose=False):
if author["e"] is not None:
if author["e"] not in name_map:
unknown_emails.add(
f'{author["e"].ljust(29)} '
f"{author['e'].ljust(29)} "
"https://github.com/mne-tools/mne-python/pull/"
f"{commit}/files"
)
Expand All @@ -178,9 +178,9 @@ def generate_credit_rst(app=None, *, verbose=False):
else:
name = author["n"]
if name in manual_renames:
assert _good_name(
manual_renames[name]
), f"Bad manual rename: {name}"
assert _good_name(manual_renames[name]), (
f"Bad manual rename: {name}"
)
name = manual_renames[name]
if " " in name:
first, last = name.rsplit(" ", maxsplit=1)
Expand Down
6 changes: 3 additions & 3 deletions doc/sphinxext/related_software.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ def _get_packages() -> dict[str, str]:
assert not dups, f"Duplicates in MANUAL_PACKAGES and PYPI_PACKAGES: {sorted(dups)}"
# And the installer and PyPI-only should be disjoint:
dups = set(PYPI_PACKAGES) & set(packages)
assert (
not dups
), f"Duplicates in PYPI_PACKAGES and installer packages: {sorted(dups)}"
assert not dups, (
f"Duplicates in PYPI_PACKAGES and installer packages: {sorted(dups)}"
)
for name in PYPI_PACKAGES | set(MANUAL_PACKAGES):
if name not in packages:
packages.append(name)
Expand Down
3 changes: 1 addition & 2 deletions doc/sphinxext/unit_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ def unit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): #

def pass_error_to_sphinx(rawtext, text, lineno, inliner):
msg = inliner.reporter.error(
"The :unit: role requires a space-separated number and unit; "
f"got {text}",
f"The :unit: role requires a space-separated number and unit; got {text}",
line=lineno,
)
prb = inliner.problematic(rawtext, rawtext, msg)
Expand Down
2 changes: 1 addition & 1 deletion examples/inverse/vector_mne_solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
# inverse was computed with loose=0.2
print(
"Absolute cosine similarity between source normals and directions: "
f'{np.abs(np.sum(directions * inv["source_nn"][2::3], axis=-1)).mean()}'
f"{np.abs(np.sum(directions * inv['source_nn'][2::3], axis=-1)).mean()}"
)
brain_max = stc_max.plot(
initial_time=peak_time,
Expand Down
4 changes: 2 additions & 2 deletions examples/visualization/evoked_topomap.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Plotting topographic maps of evoked data
========================================
Load evoked data and plot topomaps for selected time points using multiple
additional options.
Load evoked data and plot topomaps for selected time points using
multiple additional options.
"""
# Authors: Christian Brodbeck <[email protected]>
# Tal Linzen <[email protected]>
Expand Down
2 changes: 1 addition & 1 deletion examples/visualization/evoked_whitening.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

print("Covariance estimates sorted from best to worst")
for c in noise_covs:
print(f'{c["method"]} : {c["loglik"]}')
print(f"{c['method']} : {c['loglik']}")

# %%
# Show the evoked data:
Expand Down
3 changes: 1 addition & 2 deletions mne/_fiff/_digitization.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,7 @@ def _get_data_as_dict_from_dig(dig, exclude_ref_channel=True):
dig_coord_frames = set([FIFF.FIFFV_COORD_HEAD])
if len(dig_coord_frames) != 1:
raise RuntimeError(
"Only single coordinate frame in dig is supported, "
f"got {dig_coord_frames}"
f"Only single coordinate frame in dig is supported, got {dig_coord_frames}"
)
dig_ch_pos_location = np.array(dig_ch_pos_location)
dig_ch_pos_location.shape = (-1, 3) # empty will be (0, 3)
Expand Down
7 changes: 3 additions & 4 deletions mne/_fiff/meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ def _check_set(ch, projs, ch_type):
for proj in projs:
if ch["ch_name"] in proj["data"]["col_names"]:
raise RuntimeError(
f'Cannot change channel type for channel {ch["ch_name"]} in '
f"Cannot change channel type for channel {ch['ch_name']} in "
f'projector "{proj["desc"]}"'
)
ch["kind"] = new_kind
Expand Down Expand Up @@ -1867,7 +1867,7 @@ def _check_consistency(self, prepend_error=""):
):
raise RuntimeError(
f'{prepend_error}info["meas_date"] must be a datetime object in UTC'
f' or None, got {repr(self["meas_date"])!r}'
f" or None, got {repr(self['meas_date'])!r}"
)

chs = [ch["ch_name"] for ch in self["chs"]]
Expand Down Expand Up @@ -3680,8 +3680,7 @@ def _write_ch_infos(fid, chs, reset_range, ch_names_mapping):
# only write new-style channel information if necessary
if len(ch_names_mapping):
logger.info(
" Writing channel names to FIF truncated to 15 characters "
"with remapping"
" Writing channel names to FIF truncated to 15 characters with remapping"
)
for ch in chs:
start_block(fid, FIFF.FIFFB_CH_INFO)
Expand Down
16 changes: 7 additions & 9 deletions mne/_fiff/proj.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def __repr__(self): # noqa: D105
s += f", active : {self['active']}"
s += f", n_channels : {len(self['data']['col_names'])}"
if self["explained_var"] is not None:
s += f', exp. var : {self["explained_var"] * 100:0.2f}%'
s += f", exp. var : {self['explained_var'] * 100:0.2f}%"
return f"<Projection | {s}>"

# speed up info copy by taking advantage of mutability
Expand Down Expand Up @@ -324,8 +324,7 @@ def apply_proj(self, verbose=None):

if all(p["active"] for p in self.info["projs"]):
logger.info(
"Projections have already been applied. "
"Setting proj attribute to True."
"Projections have already been applied. Setting proj attribute to True."
)
return self

Expand Down Expand Up @@ -663,9 +662,9 @@ def _read_proj(fid, node, *, ch_names_mapping=None, verbose=None):
for proj in projs:
misc = "active" if proj["active"] else " idle"
logger.info(
f' {proj["desc"]} '
f'({proj["data"]["nrow"]} x '
f'{len(proj["data"]["col_names"])}) {misc}'
f" {proj['desc']} "
f"({proj['data']['nrow']} x "
f"{len(proj['data']['col_names'])}) {misc}"
)

return projs
Expand Down Expand Up @@ -795,8 +794,7 @@ def _make_projector(projs, ch_names, bads=(), include_active=True, inplace=False
if not p["active"] or include_active:
if len(p["data"]["col_names"]) != len(np.unique(p["data"]["col_names"])):
raise ValueError(
f"Channel name list in projection item {k}"
" contains duplicate items"
f"Channel name list in projection item {k} contains duplicate items"
)

# Get the two selection vectors to pick correct elements from
Expand Down Expand Up @@ -832,7 +830,7 @@ def _make_projector(projs, ch_names, bads=(), include_active=True, inplace=False
)
):
warn(
f'Projection vector {repr(p["desc"])} has been '
f"Projection vector {repr(p['desc'])} has been "
f"reduced to {100 * psize:0.2f}% of its "
"original magnitude by subselecting "
f"{len(vecsel)}/{orig_n} of the original "
Expand Down
6 changes: 3 additions & 3 deletions mne/_fiff/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def _check_before_dict_reference(inst, ref_dict):
raise TypeError(
f"{elem_name.capitalize()}s in the ref_channels dict must be strings. "
f"Your dict has {elem_name}s of type "
f'{", ".join(map(lambda x: x.__name__, bad_elem))}.'
f"{', '.join(map(lambda x: x.__name__, bad_elem))}."
)

# Check that keys are valid channels and values are lists-of-valid-channels
Expand All @@ -113,8 +113,8 @@ def _check_before_dict_reference(inst, ref_dict):
for elem_name, elem in dict(key=keys, value=values).items():
if bad_elem := elem - ch_set:
raise ValueError(
f'ref_channels dict contains invalid {elem_name}(s) '
f'({", ".join(bad_elem)}) '
f"ref_channels dict contains invalid {elem_name}(s) "
f"({', '.join(bad_elem)}) "
"that are not names of channels in the instance."
)
# Check that values are not bad channels
Expand Down
3 changes: 1 addition & 2 deletions mne/_fiff/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ def _frombuffer_rows(fid, tag_size, dtype=None, shape=None, rlims=None):
have_shape = tag_size // item_size
if want_shape != have_shape:
raise ValueError(
f"Wrong shape specified, requested {want_shape} but got "
f"{have_shape}"
f"Wrong shape specified, requested {want_shape} but got {have_shape}"
)
if not len(rlims) == 2:
raise ValueError("rlims must have two elements")
Expand Down
2 changes: 1 addition & 1 deletion mne/_fiff/tests/test_meas_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -1118,7 +1118,7 @@ def test_channel_name_limit(tmp_path, monkeypatch, fname):
meas_info, "_read_extended_ch_info", _read_extended_ch_info
)
short_proj_names = [
f"{name[:13 - bool(len(ref_names))]}-{ni}"
f"{name[: 13 - bool(len(ref_names))]}-{ni}"
for ni, name in enumerate(long_proj_names)
]
assert raw_read.info["projs"][0]["data"]["col_names"] == short_proj_names
Expand Down
2 changes: 1 addition & 1 deletion mne/_fiff/tests/test_pick.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def _channel_type_old(info, idx):
else:
return t

raise ValueError(f'Unknown channel type for {ch["ch_name"]}')
raise ValueError(f"Unknown channel type for {ch['ch_name']}")


def _assert_channel_types(info):
Expand Down
10 changes: 5 additions & 5 deletions mne/beamformer/_compute_beamformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,13 +507,13 @@ def __repr__(self): # noqa: D105
n_channels,
)
if self["pick_ori"] is not None:
out += f', {self["pick_ori"]} ori'
out += f", {self['pick_ori']} ori"
if self["weight_norm"] is not None:
out += f', {self["weight_norm"]} norm'
out += f", {self['weight_norm']} norm"
if self.get("inversion") is not None:
out += f', {self["inversion"]} inversion'
out += f", {self['inversion']} inversion"
if "rank" in self:
out += f', rank {self["rank"]}'
out += f", rank {self['rank']}"
out += ">"
return out

Expand All @@ -531,7 +531,7 @@ def save(self, fname, overwrite=False, verbose=None):
"""
_, write_hdf5 = _import_h5io_funcs()

ending = f'-{self["kind"].lower()}.h5'
ending = f"-{self['kind'].lower()}.h5"
check_fname(fname, self["kind"], (ending,))
csd_orig = None
try:
Expand Down
2 changes: 1 addition & 1 deletion mne/beamformer/tests/test_lcmv.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ def test_make_lcmv_bem(tmp_path, reg, proj, kind):
rank = 17 if proj else 20
assert "LCMV" in repr(filters)
assert "unknown subject" not in repr(filters)
assert f'{fwd["nsource"]} vert' in repr(filters)
assert f"{fwd['nsource']} vert" in repr(filters)
assert "20 ch" in repr(filters)
assert f"rank {rank}" in repr(filters)

Expand Down
14 changes: 6 additions & 8 deletions mne/bem.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class ConductorModel(dict):

def __repr__(self): # noqa: D105
if self["is_sphere"]:
center = ", ".join(f"{x * 1000.:.1f}" for x in self["r0"])
center = ", ".join(f"{x * 1000.0:.1f}" for x in self["r0"])
rad = self.radius
if rad is None: # no radius / MEG only
extra = f"Sphere (no layers): r0=[{center}] mm"
Expand Down Expand Up @@ -538,7 +538,7 @@ def _assert_complete_surface(surf, incomplete="raise"):
prop = tot_angle / (2 * np.pi)
if np.abs(prop - 1.0) > 1e-5:
msg = (
f'Surface {_bem_surf_name[surf["id"]]} is not complete (sum of '
f"Surface {_bem_surf_name[surf['id']]} is not complete (sum of "
f"solid angles yielded {prop}, should be 1.)"
)
_on_missing(incomplete, msg, name="incomplete", error_klass=RuntimeError)
Expand Down Expand Up @@ -571,7 +571,7 @@ def _check_surface_size(surf):
sizes = surf["rr"].max(axis=0) - surf["rr"].min(axis=0)
if (sizes < 0.05).any():
raise RuntimeError(
f'Dimensions of the surface {_bem_surf_name[surf["id"]]} seem too '
f"Dimensions of the surface {_bem_surf_name[surf['id']]} seem too "
f"small ({1000 * sizes.min():9.5f}). Maybe the unit of measure"
" is meters instead of mm"
)
Expand Down Expand Up @@ -599,8 +599,7 @@ def _surfaces_to_bem(
# surfs can be strings (filenames) or surface dicts
if len(surfs) not in (1, 3) or not (len(surfs) == len(ids) == len(sigmas)):
raise ValueError(
"surfs, ids, and sigmas must all have the same "
"number of elements (1 or 3)"
"surfs, ids, and sigmas must all have the same number of elements (1 or 3)"
)
for si, surf in enumerate(surfs):
if isinstance(surf, str | Path | os.PathLike):
Expand Down Expand Up @@ -1260,8 +1259,7 @@ def make_watershed_bem(
if op.isdir(ws_dir):
if not overwrite:
raise RuntimeError(
f"{ws_dir} already exists. Use the --overwrite option"
" to recreate it."
f"{ws_dir} already exists. Use the --overwrite option to recreate it."
)
else:
shutil.rmtree(ws_dir)
Expand Down Expand Up @@ -2460,7 +2458,7 @@ def check_seghead(surf_path=subj_path / "surf"):
logger.info(f"{ii}. Creating {level} tessellation...")
logger.info(
f"{ii}.1 Decimating the dense tessellation "
f'({len(surf["tris"])} -> {n_tri} triangles)...'
f"({len(surf['tris'])} -> {n_tri} triangles)..."
)
points, tris = decimate_surface(
points=surf["rr"], triangles=surf["tris"], n_triangles=n_tri
Expand Down
2 changes: 1 addition & 1 deletion mne/channels/channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,7 @@ def read_ch_adjacency(fname, picks=None):
raise ValueError(
f"No built-in channel adjacency matrix found with name: "
f"{ch_adj_name}. Valid names are: "
f'{", ".join(get_builtin_ch_adjacencies())}'
f"{', '.join(get_builtin_ch_adjacencies())}"
)

ch_adj = [a for a in _BUILTIN_CHANNEL_ADJACENCIES if a.name == ch_adj_name][0]
Expand Down
2 changes: 1 addition & 1 deletion mne/channels/montage.py
Original file line number Diff line number Diff line change
Expand Up @@ -1287,7 +1287,7 @@ def _backcompat_value(pos, ref_pos):
f"Not setting position{_pl(extra)} of {len(extra)} {types} "
f"channel{_pl(extra)} found in montage:\n{names}\n"
"Consider setting the channel types to be of "
f'{docdict["montage_types"]} '
f"{docdict['montage_types']} "
"using inst.set_channel_types before calling inst.set_montage, "
"or omit these channels when creating your montage."
)
Expand Down
3 changes: 1 addition & 2 deletions mne/channels/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,7 @@ def test_adjacency_matches_ft(tmp_path):

if hash_mne.hexdigest() != hash_ft.hexdigest():
raise ValueError(
f"Hash mismatch between built-in and FieldTrip neighbors "
f"for {fname}"
f"Hash mismatch between built-in and FieldTrip neighbors for {fname}"
)


Expand Down
7 changes: 1 addition & 6 deletions mne/channels/tests/test_montage.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,12 +420,7 @@ def test_documented():
),
pytest.param(
partial(read_dig_hpts, unit="m"),
(
"eeg Fp1 -95.0 -3. -3.\n"
"eeg AF7 -1 -1 -3\n"
"eeg A3 -2 -2 2\n"
"eeg A 0 0 0"
),
("eeg Fp1 -95.0 -3. -3.\neeg AF7 -1 -1 -3\neeg A3 -2 -2 2\neeg A 0 0 0"),
make_dig_montage(
ch_pos={
"A": [0.0, 0.0, 0.0],
Expand Down
3 changes: 1 addition & 2 deletions mne/commands/mne_make_scalp_surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ def run():
"--force",
dest="force",
action="store_true",
help="Force creation of the surface even if it has "
"some topological defects.",
help="Force creation of the surface even if it has some topological defects.",
)
parser.add_option(
"-t",
Expand Down
Loading

0 comments on commit 98a0891

Please sign in to comment.