Skip to content

Commit cafa255

Browse files
committed
Merge remote-tracking branch 'upstream/main' into nk
* upstream/main: ENH: Add encoding parameter to Nihon Kohden reader (mne-tools#13458) [MAINT] Automatic SPEC0 dependency version management (mne-tools#13451)
2 parents a0b126e + 147ff59 commit cafa255

File tree

8 files changed

+347
-15
lines changed

8 files changed

+347
-15
lines changed

.github/workflows/spec_zero.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: SPEC0
2+
3+
on: # yamllint disable-line rule:truthy
4+
schedule:
5+
- cron: '0 0 * * 1' # At 00:00 every Monday
6+
workflow_dispatch:
7+
inputs:
8+
ssh:
9+
description: 'Enable ssh debugging'
10+
required: false
11+
default: false
12+
type: boolean
13+
14+
jobs:
15+
update_versions:
16+
permissions:
17+
contents: write
18+
pull-requests: write
19+
name: Update dependency versions
20+
runs-on: ubuntu-latest
21+
env:
22+
GH_TOKEN: ${{ github.token }}
23+
GITHUB_TOKEN: ${{ github.token }}
24+
steps:
25+
- uses: actions/checkout@v5
26+
with:
27+
persist-credentials: true
28+
- name: Triage SSH
29+
run: |
30+
if [[ "${{ inputs.ssh }}" == "true" ]] || [[ "$COMMIT_MESSAGE" == *"[actions ssh]"* ]]; then
31+
echo "ENABLE_SSH=true" | tee -a $GITHUB_ENV
32+
else
33+
echo "ENABLE_SSH=false" | tee -a $GITHUB_ENV
34+
fi
35+
- name: Setup Remote SSH Connection
36+
if: env.ENABLE_SSH == 'true'
37+
uses: mxschmitt/action-tmate@v3
38+
timeout-minutes: 10
39+
with:
40+
detached: true
41+
- uses: actions/setup-python@v6
42+
with:
43+
python-version: '3.12'
44+
- run: pip install packaging requests tomlkit
45+
- run: python tools/dev/spec_zero_update_versions.py
46+
- run: |
47+
git diff && git status --porcelain
48+
if [[ $(git status --porcelain) ]]; then
49+
echo "dirty=true" >> $GITHUB_OUTPUT
50+
fi
51+
id: status
52+
- name: Create PR
53+
run: |
54+
set -xeo pipefail
55+
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
56+
git config --global user.name "github-actions[bot]"
57+
git checkout -b spec_zero
58+
git commit -am "MAINT: Update dependency specifiers"
59+
git push origin spec_zero
60+
PR_NUM=$(gh pr create --base main --head spec_zero --title "MAINT: Update dependency specifiers" --body "Created by spec_zero [GitHub action](https://github.com/mne-tools/mne-python/actions/runs/${{ github.run_id }})." --label "no-changelog-entry-needed")
61+
echo "Opened https://github.com/mne-tools/mne-python/pull/${PR_NUM}" >> $GITHUB_STEP_SUMMARY
62+
if: steps.status.outputs.dirty == 'true'

.yamllint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ ignore: |
66
rules:
77
line-length: disable
88
document-start: disable
9+
new-lines:
10+
type: platform

doc/changes/dev/13451.other.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a SPEC0-like policy in which minimum-supported versions for select dependencies are set to the latest minor release that was available 2 years prior, by `Thomas Binns`_
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``encoding`` parameter to :func:`mne.io.read_raw_nihon` for better handling of annotation decoding, by `Tom Ma`_.

mne/io/nihon/nihon.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ def _ensure_path(fname):
2323

2424

2525
@fill_doc
26-
def read_raw_nihon(fname, preload=False, verbose=None) -> "RawNihon":
26+
def read_raw_nihon(
27+
fname, preload=False, *, encoding="utf-8", verbose=None
28+
) -> "RawNihon":
2729
"""Reader for an Nihon Kohden EEG file.
2830
2931
Parameters
@@ -32,6 +34,9 @@ def read_raw_nihon(fname, preload=False, verbose=None) -> "RawNihon":
3234
Path to the Nihon Kohden data file (``.EEG``).
3335
preload : bool
3436
If True, all data are loaded at initialization.
37+
%(encoding_nihon)s
38+
39+
.. versionadded:: 1.11
3540
%(verbose)s
3641
3742
Returns
@@ -44,7 +49,7 @@ def read_raw_nihon(fname, preload=False, verbose=None) -> "RawNihon":
4449
--------
4550
mne.io.Raw : Documentation of attributes and methods of RawNihon.
4651
"""
47-
return RawNihon(fname, preload, verbose)
52+
return RawNihon(fname, preload, encoding=encoding, verbose=verbose)
4853

4954

5055
_valid_headers = [
@@ -317,7 +322,7 @@ def _parse_sub_event_log(sub_event_log):
317322
return t_sub_desc, t_sub_onset
318323

319324

320-
def _read_nihon_annotations(fname):
325+
def _read_nihon_annotations(fname, encoding="utf-8"):
321326
fname = _ensure_path(fname)
322327
log_fname = fname.with_suffix(".LOG")
323328
if not log_fname.exists():
@@ -348,15 +353,10 @@ def _read_nihon_annotations(fname):
348353
t_onset += t_sub_onset
349354

350355
t_desc = t_desc.rstrip(b"\x00")
351-
for enc in _encodings:
352-
try:
353-
t_desc = t_desc.decode(enc)
354-
except UnicodeDecodeError:
355-
pass
356-
else:
357-
break
358-
else:
359-
warn(f"Could not decode log as one of {_encodings}")
356+
try:
357+
t_desc = t_desc.decode(encoding)
358+
except UnicodeDecodeError:
359+
warn(f"Could not decode log as {encoding}")
360360
continue
361361

362362
all_onsets.append(t_onset)
@@ -416,6 +416,9 @@ class RawNihon(BaseRaw):
416416
Path to the Nihon Kohden data ``.eeg`` file.
417417
preload : bool
418418
If True, all data are loaded at initialization.
419+
%(encoding_nihon)s
420+
421+
.. versionadded:: 1.11
419422
%(verbose)s
420423
421424
See Also
@@ -424,7 +427,7 @@ class RawNihon(BaseRaw):
424427
"""
425428

426429
@verbose
427-
def __init__(self, fname, preload=False, verbose=None):
430+
def __init__(self, fname, preload=False, *, encoding="utf-8", verbose=None):
428431
fname = _check_fname(fname, "read", True, "fname")
429432
data_name = fname.name
430433
logger.info(f"Loading {data_name}")
@@ -470,7 +473,7 @@ def __init__(self, fname, preload=False, verbose=None):
470473
)
471474

472475
# Get annotations from LOG file
473-
annots = _read_nihon_annotations(fname)
476+
annots = _read_nihon_annotations(fname, encoding)
474477

475478
# Annotate acquisition skips
476479
controlblock = header["controlblocks"][0]

mne/utils/docs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,11 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
12851285
encoding according to the EDF+ standard).
12861286
"""
12871287

1288+
docdict["encoding_nihon"] = """
1289+
encoding : str
1290+
Text encoding of Nihon Kohden annotations. See :ref:`standard-encodings`.
1291+
"""
1292+
12881293
docdict["encoding_nirx"] = """
12891294
encoding : str
12901295
Text encoding of the NIRX header file. See :ref:`standard-encodings`.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ full-no-qt = [
111111
"nibabel",
112112
"nilearn",
113113
"numba",
114-
"openmeeg >= 2.5.7", # released: 2023/11/16
114+
"openmeeg >= 2.5.7",
115115
"pandas >= 2.1", # released: 2023/08/30
116116
"pillow", # for `Brain.save_image` and `mne.Report`
117117
"pyarrow", # only needed to avoid a deprecation warning in pandas

0 commit comments

Comments
 (0)