Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/mne-tools/mne-python into e…
Browse files Browse the repository at this point in the history
…poch_reject
  • Loading branch information
withmywoessner committed Jan 24, 2024
2 parents a11a410 + 03d78f4 commit b918ea8
Show file tree
Hide file tree
Showing 44 changed files with 169 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ jobs:
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'
- run: ./tools/get_testing_version.sh
- uses: actions/cache@v3
- uses: actions/cache@v4
with:
key: ${{ env.TESTING_VERSION }}
path: ~/mne_data
Expand Down
1 change: 1 addition & 0 deletions doc/changes/devel/12380.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix bug where :func:`mne.preprocessing.compute_proj_ecg` and :func:`mne.preprocessing.compute_proj_eog` could modify the default ``reject`` and ``flat`` arguments on multiple calls based on channel types present, by `Eric Larson`_.
1 change: 1 addition & 0 deletions doc/changes/devel/12383.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ability to detect minima peaks found in :class:`mne.Evoked` if data is all positive and maxima if data is all negative.
5 changes: 5 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,10 @@ def reset_warnings(gallery_conf, fname):
r"ast\.NameConstant is deprecated and will be removed in Python 3\.14",
# pooch
r"Python 3\.14 will, by default, filter extracted tar archives.*",
# seaborn
r"DataFrameGroupBy\.apply operated on the grouping columns.*",
# pandas
r"\nPyarrow will become a required dependency of pandas.*",
):
warnings.filterwarnings( # deal with other modules having bad imports
"ignore", message=".*%s.*" % key, category=DeprecationWarning
Expand Down Expand Up @@ -1382,6 +1386,7 @@ def reset_warnings(gallery_conf, fname):
r"iteritems is deprecated.*Use \.items instead\.",
"is_categorical_dtype is deprecated.*",
"The default of observed=False.*",
"When grouping with a length-1 list-like.*",
):
warnings.filterwarnings(
"ignore",
Expand Down
1 change: 1 addition & 0 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ dependencies:
- pip
- numpy
- scipy
- openblas!=0.3.26 # until https://github.com/conda-forge/scipy-feedstock/pull/268 lands
- matplotlib
- tqdm
- pooch>=1.5
Expand Down
2 changes: 2 additions & 0 deletions examples/time_frequency/time_frequency_erds.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
# %%
# First, we load and preprocess the data. We use runs 6, 10, and 14 from
# subject 1 (these runs contains hand and feet motor imagery).

fnames = eegbci.load_data(subject=1, runs=(6, 10, 14))
raw = concatenate_raws([read_raw_edf(f, preload=True) for f in fnames])

Expand All @@ -59,6 +60,7 @@

# %%
# Now we can create 5-second epochs around events of interest.

tmin, tmax = -1, 4
event_ids = dict(hands=2, feet=3) # map event IDs to tasks

Expand Down
2 changes: 1 addition & 1 deletion mne/_fiff/open.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def show_fiff(
return out


def _find_type(value, fmts=["FIFF_"], exclude=["FIFF_UNIT"]):
def _find_type(value, fmts=("FIFF_",), exclude=("FIFF_UNIT",)):
"""Find matching values."""
value = int(value)
vals = [
Expand Down
10 changes: 5 additions & 5 deletions mne/_fiff/pick.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ def channel_type(info, idx):


@verbose
def pick_channels(ch_names, include, exclude=[], ordered=None, *, verbose=None):
def pick_channels(ch_names, include, exclude=(), ordered=None, *, verbose=None):
"""Pick channels by names.
Returns the indices of ``ch_names`` in ``include`` but not in ``exclude``.
Expand Down Expand Up @@ -706,7 +706,7 @@ def _has_kit_refs(info, picks):

@verbose
def pick_channels_forward(
orig, include=[], exclude=[], ordered=None, copy=True, *, verbose=None
orig, include=(), exclude=(), ordered=None, copy=True, *, verbose=None
):
"""Pick channels from forward operator.
Expand Down Expand Up @@ -797,8 +797,8 @@ def pick_types_forward(
seeg=False,
ecog=False,
dbs=False,
include=[],
exclude=[],
include=(),
exclude=(),
):
"""Pick by channel type and names from a forward operator.
Expand Down Expand Up @@ -893,7 +893,7 @@ def channel_indices_by_type(info, picks=None):

@verbose
def pick_channels_cov(
orig, include=[], exclude="bads", ordered=None, copy=True, *, verbose=None
orig, include=(), exclude="bads", ordered=None, copy=True, *, verbose=None
):
"""Pick channels from covariance matrix.
Expand Down
4 changes: 2 additions & 2 deletions mne/channels/tests/test_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,8 @@ def test_1020_selection():
raw = raw.rename_channels(dict(zip(raw.ch_names, montage.ch_names)))
raw.set_montage(montage)

for input in ("a_string", 100, raw, [1, 2]):
pytest.raises(TypeError, make_1020_channel_selections, input)
for input_ in ("a_string", 100, raw, [1, 2]):
pytest.raises(TypeError, make_1020_channel_selections, input_)

sels = make_1020_channel_selections(raw.info)
# are all frontal channels placed before all occipital channels?
Expand Down
12 changes: 7 additions & 5 deletions mne/commands/mne_setup_source_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def run():
subjects_dir = options.subjects_dir
spacing = options.spacing
ico = options.ico
oct = options.oct
oct_ = options.oct
surface = options.surface
n_jobs = options.n_jobs
add_dist = options.add_dist
Expand All @@ -130,20 +130,22 @@ def run():
overwrite = True if options.overwrite is not None else False

# Parse source spacing option
spacing_options = [ico, oct, spacing]
spacing_options = [ico, oct_, spacing]
n_options = len([x for x in spacing_options if x is not None])
use_spacing = "oct6"
if n_options > 1:
raise ValueError("Only one spacing option can be set at the same time")
elif n_options == 0:
# Default to oct6
use_spacing = "oct6"
pass
elif n_options == 1:
if ico is not None:
use_spacing = "ico" + str(ico)
elif oct is not None:
use_spacing = "oct" + str(oct)
elif oct_ is not None:
use_spacing = "oct" + str(oct_)
elif spacing is not None:
use_spacing = spacing
del ico, oct_, spacing
# Generate filename
if fname is None:
if subject_to is None:
Expand Down
2 changes: 1 addition & 1 deletion mne/cov.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def __iadd__(self, cov):
def plot(
self,
info,
exclude=[],
exclude=(),
colorbar=True,
proj=False,
show_svd=True,
Expand Down
4 changes: 2 additions & 2 deletions mne/datasets/sleep_physionet/tests/test_physionet.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ def _check_mocked_function_calls(mocked_func, call_fname_hash_pairs, base_path):
# order.
for idx, current in enumerate(call_fname_hash_pairs):
_, call_kwargs = mocked_func.call_args_list[idx]
hash_type, hash = call_kwargs["known_hash"].split(":")
hash_type, hash_ = call_kwargs["known_hash"].split(":")
assert call_kwargs["url"] == _get_expected_url(current["name"]), idx
assert Path(call_kwargs["path"], call_kwargs["fname"]) == _get_expected_path(
base_path, current["name"]
)
assert hash == current["hash"]
assert hash_ == current["hash"]
assert hash_type == "sha1"


Expand Down
2 changes: 1 addition & 1 deletion mne/decoding/tests/test_ssd.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


def simulate_data(
freqs_sig=[9, 12],
freqs_sig=(9, 12),
n_trials=100,
n_channels=20,
n_samples=500,
Expand Down
4 changes: 2 additions & 2 deletions mne/epochs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3684,7 +3684,7 @@ def _is_good(
reject,
flat,
full_report=False,
ignore_chs=[],
ignore_chs=(),
verbose=None,
):
"""Test if data segment e is good according to reject and flat.
Expand Down Expand Up @@ -4685,7 +4685,7 @@ def make_fixed_length_epochs(
reject_by_annotation=True,
proj=True,
overlap=0.0,
id=1,
id=1, # noqa: A002
verbose=None,
):
"""Divide continuous raw data into equal-sized consecutive epochs.
Expand Down
8 changes: 7 additions & 1 deletion mne/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,13 @@ def shift_time_events(events, ids, tshift, sfreq):

@fill_doc
def make_fixed_length_events(
raw, id=1, start=0, stop=None, duration=1.0, first_samp=True, overlap=0.0
raw,
id=1, # noqa: A002
start=0,
stop=None,
duration=1.0,
first_samp=True,
overlap=0.0,
):
"""Make a set of :term:`events` separated by a fixed duration.
Expand Down
29 changes: 24 additions & 5 deletions mne/evoked.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ def plot_topo(
scalings=None,
title=None,
proj=False,
vline=[0.0],
vline=(0.0,),
fig_background=None,
merge_grads=False,
legend=True,
Expand Down Expand Up @@ -914,6 +914,8 @@ def get_peak(
time_as_index=False,
merge_grads=False,
return_amplitude=False,
*,
strict=True,
):
"""Get location and latency of peak amplitude.
Expand Down Expand Up @@ -941,6 +943,12 @@ def get_peak(
If True, return also the amplitude at the maximum response.
.. versionadded:: 0.16
strict : bool
If True, raise an error if values are all positive when detecting
a minimum (mode='neg'), or all negative when detecting a maximum
(mode='pos'). Defaults to True.
.. versionadded:: 1.7
Returns
-------
Expand Down Expand Up @@ -1032,7 +1040,14 @@ def get_peak(
data, _ = _merge_ch_data(data, ch_type, [])
ch_names = [ch_name[:-1] + "X" for ch_name in ch_names[::2]]

ch_idx, time_idx, max_amp = _get_peak(data, self.times, tmin, tmax, mode)
ch_idx, time_idx, max_amp = _get_peak(
data,
self.times,
tmin,
tmax,
mode,
strict=strict,
)

out = (ch_names[ch_idx], time_idx if time_as_index else self.times[time_idx])

Expand Down Expand Up @@ -1949,7 +1964,7 @@ def _write_evokeds(fname, evoked, check=True, *, on_mismatch="raise", overwrite=
end_block(fid, FIFF.FIFFB_MEAS)


def _get_peak(data, times, tmin=None, tmax=None, mode="abs"):
def _get_peak(data, times, tmin=None, tmax=None, mode="abs", *, strict=True):
"""Get feature-index and time of maximum signal from 2D array.
Note. This is a 'getter', not a 'finder'. For non-evoked type
Expand All @@ -1970,6 +1985,10 @@ def _get_peak(data, times, tmin=None, tmax=None, mode="abs"):
values will be considered. If 'neg' only negative values will
be considered. If 'abs' absolute values will be considered.
Defaults to 'abs'.
strict : bool
If True, raise an error if values are all positive when detecting
a minimum (mode='neg'), or all negative when detecting a maximum
(mode='pos'). Defaults to True.
Returns
-------
Expand Down Expand Up @@ -2008,12 +2027,12 @@ def _get_peak(data, times, tmin=None, tmax=None, mode="abs"):

maxfun = np.argmax
if mode == "pos":
if not np.any(data[~mask] > 0):
if strict and not np.any(data[~mask] > 0):
raise ValueError(
"No positive values encountered. Cannot " "operate in pos mode."
)
elif mode == "neg":
if not np.any(data[~mask] < 0):
if strict and not np.any(data[~mask] < 0):
raise ValueError(
"No negative values encountered. Cannot " "operate in neg mode."
)
Expand Down
4 changes: 2 additions & 2 deletions mne/export/_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ def _infer_check_export_fmt(fmt, fname, supported_formats):

if fmt not in supported_formats:
supported = []
for format, extensions in supported_formats.items():
for supp_format, extensions in supported_formats.items():
ext_str = ", ".join(f"*.{ext}" for ext in extensions)
supported.append(f"{format} ({ext_str})")
supported.append(f"{supp_format} ({ext_str})")

supported_str = ", ".join(supported)
raise ValueError(
Expand Down
4 changes: 2 additions & 2 deletions mne/gui/_coreg.py
Original file line number Diff line number Diff line change
Expand Up @@ -1907,7 +1907,7 @@ def _configure_dock(self):
func=self._save_trans,
tooltip="Save the transform file to disk",
layout=save_trans_layout,
filter="Head->MRI transformation (*-trans.fif *_trans.fif)",
filter_="Head->MRI transformation (*-trans.fif *_trans.fif)",
initial_directory=str(Path(self._info_file).parent),
)
self._widgets["load_trans"] = self._renderer._dock_add_file_button(
Expand All @@ -1916,7 +1916,7 @@ def _configure_dock(self):
func=self._load_trans,
tooltip="Load the transform file from disk",
layout=save_trans_layout,
filter="Head->MRI transformation (*-trans.fif *_trans.fif)",
filter_="Head->MRI transformation (*-trans.fif *_trans.fif)",
initial_directory=str(Path(self._info_file).parent),
)
self._renderer._layout_add_widget(trans_layout, save_trans_layout)
Expand Down
2 changes: 1 addition & 1 deletion mne/inverse_sparse/mxne_optim.py
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ def __call__(self, x): # noqa: D105
else:
return np.hstack([x @ op for op in self.ops]) / np.sqrt(self.n_dicts)

def norm(self, z, ord=2):
def norm(self, z, ord=2): # noqa: A002
"""Squared L2 norm if ord == 2 and L1 norm if order == 1."""
if ord not in (1, 2):
raise ValueError(
Expand Down
2 changes: 1 addition & 1 deletion mne/io/bti/bti.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def __init__(self, target):
def __enter__(self): # noqa: D105
return self.target

def __exit__(self, type, value, tb): # noqa: D105
def __exit__(self, exception_type, value, tb): # noqa: D105
pass


Expand Down
6 changes: 3 additions & 3 deletions mne/io/curry/curry.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ def _read_curry_parameters(fname):
if any(var_name in line for var_name in var_names):
key, val = line.replace(" ", "").replace("\n", "").split("=")
param_dict[key.lower().replace("_", "")] = val
for type in CHANTYPES:
if "DEVICE_PARAMETERS" + CHANTYPES[type] + " START" in line:
for key, type_ in CHANTYPES.items():
if f"DEVICE_PARAMETERS{type_} START" in line:
data_unit = next(fid)
unit_dict[type] = (
unit_dict[key] = (
data_unit.replace(" ", "").replace("\n", "").split("=")[-1]
)

Expand Down
4 changes: 3 additions & 1 deletion mne/io/edf/edf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,9 @@ def _read_gdf_header(fname, exclude, include=None):


def _check_stim_channel(
stim_channel, ch_names, tal_ch_names=["EDF Annotations", "BDF Annotations"]
stim_channel,
ch_names,
tal_ch_names=("EDF Annotations", "BDF Annotations"),
):
"""Check that the stimulus channel exists in the current datafile."""
DEFAULT_STIM_CH_NAMES = ["status", "trigger"]
Expand Down
2 changes: 1 addition & 1 deletion mne/io/fieldtrip/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def get_epochs(system):
else:
event_id = [int(cfg_local["eventvalue"])]

event_id = [id for id in event_id if id in events[:, 2]]
event_id = [id_ for id_ in event_id if id_ in events[:, 2]]

epochs = mne.Epochs(
raw_data,
Expand Down
Loading

0 comments on commit b918ea8

Please sign in to comment.