Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for dictionary-type ref_channels in set_eeg_reference() #12366

Merged
merged 72 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
1bce965
init the PR draft
qian-chu Jan 16, 2024
f42d5fb
Merge branch 'main' into dict_ref
qian-chu Jan 16, 2024
278fdf3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 16, 2024
f3cff5a
Create 12366.newfeature.rst
qian-chu Jan 16, 2024
b7b5c0c
Update 12366.newfeature.rst
qian-chu Jan 17, 2024
7ece510
Merge branch 'mne-tools:main' into dict_ref
qian-chu May 2, 2024
8d4516d
Add custom reference based on dict
May 3, 2024
42f45b8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2024
95a1434
BF: use isintance to check if dict
May 3, 2024
c921d69
BF: remove extra copy of data
May 3, 2024
b0c91d2
Add custom reference
May 3, 2024
78a5c7e
change doc (add Alex)
May 3, 2024
ca6908c
Add warning if bad channels in re-referencing scheme
May 3, 2024
6ac7bed
Merge branch 'dict_ref' of https://github.com/qian-chu/mne-python int…
May 3, 2024
b1165b9
add _check_before_dict_reference and enrich set_eeg_reference_see_als…
qian-chu May 3, 2024
ed56c97
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2024
d27ce12
Update reference.py
qian-chu May 31, 2024
073ca9d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 31, 2024
8d744ca
Update test_reference.py
qian-chu May 31, 2024
9e9507d
Update reference.py
qian-chu Jun 3, 2024
24d16a5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 3, 2024
2a6db40
Update test_reference.py
qian-chu Jun 3, 2024
6699de0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 3, 2024
8a5232a
formatting
qian-chu Jun 3, 2024
73ad30d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 3, 2024
3474370
dict does not accept repeated keys, no need to test
qian-chu Jun 5, 2024
cd213ee
add test for warnings and raises
qian-chu Jun 5, 2024
6c79a60
Update test_reference.py
qian-chu Jun 5, 2024
e36ddd2
Update docs.py
qian-chu Jun 5, 2024
41893f3
Merge branch 'mne-tools:main' into dict_ref
qian-chu Jun 5, 2024
5b8bd94
Data check test
AlexLepauvre Jun 7, 2024
f354d0a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 7, 2024
6dc0633
Add check of reference flag and bug correction
AlexLepauvre Jun 7, 2024
0293e7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 7, 2024
32fa6ac
Add tests for epochs object
AlexLepauvre Jun 7, 2024
1fa6a4e
Merge branch 'dict_ref' of https://github.com/qian-chu/mne-python int…
AlexLepauvre Jun 7, 2024
18cf0d9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 7, 2024
aee05a5
Merge branch 'main' into dict_ref
qian-chu Jun 7, 2024
dcd8f9d
formatting
qian-chu Jun 10, 2024
89a4e43
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 10, 2024
c9a52d4
Add warning for re-referencing electrode by itself
AlexLepauvre Jun 19, 2024
e5cb792
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 19, 2024
f0cac35
Refactorize tests of epochs and raws
AlexLepauvre Jun 19, 2024
12ae73a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 19, 2024
10da1dd
Apply suggestions from code review
qian-chu Jun 19, 2024
d284912
Re-organize warnings and errors
qian-chu Jun 19, 2024
bc09e77
Merge branch 'main' into dict_ref
qian-chu Jun 21, 2024
0122aeb
Merge branch 'main' into dict_ref
qian-chu Jul 2, 2024
4432adc
new dict check function as suggested
qian-chu Jul 3, 2024
b3fade6
Merge branch 'main' into dict_ref
qian-chu Jul 3, 2024
d5770b0
simplify (now that we guarantee list-like dict vals)
drammock Jul 9, 2024
85d1eb1
warn when keys (not just vals) are bad chs
drammock Jul 9, 2024
eab984b
clearer var name; only compute mismatch pairs if needed
drammock Jul 9, 2024
1a57807
refactor: convert to ch indices in helper func
drammock Jul 9, 2024
dfaab21
return None (like REST/proj references) instead of copy of inst data
drammock Jul 9, 2024
6ff72b6
slightly less misleading docstring
drammock Jul 9, 2024
2ec411f
modularize check_ssp and adds the check to dict-based reference
qian-chu Jul 29, 2024
2d6eeff
Merge branch 'main' into dict_ref
qian-chu Jul 29, 2024
1025e98
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 29, 2024
8858bfc
doc improvement
qian-chu Jul 30, 2024
d39c160
Merge branch 'main' into dict_ref
qian-chu Jul 30, 2024
7dae296
Merge branch 'main' into dict_ref
qian-chu Aug 10, 2024
71b31bb
Alex not new contributor now
qian-chu Aug 23, 2024
79f5bc4
Merge branch 'main' into dict_ref
qian-chu Aug 23, 2024
7704e35
Merge branch 'dict_ref' of https://github.com/qian-chu/mne-python int…
qian-chu Aug 23, 2024
2af639b
Update 12366.newfeature.rst
qian-chu Aug 23, 2024
f677570
Update 12366.newfeature.rst
qian-chu Aug 23, 2024
85b90ff
Merge branch 'main' into dict_ref
qian-chu Sep 13, 2024
c1d0339
MAINT: Reorder
larsoner Sep 20, 2024
8297a5f
Merge branch 'main' into dict_ref
larsoner Sep 20, 2024
2ce1e8d
Merge branch 'main' into dict_ref
qian-chu Sep 21, 2024
9344a4f
Merge branch 'main' into dict_ref
qian-chu Sep 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/devel/12366.newfeature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for `dict` type argument ``ref_channels`` to :func:`mne.set_eeg_reference`, to allow flexible re-referencing, by `Qian Chu`_.
43 changes: 42 additions & 1 deletion mne/_fiff/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,44 @@ def _apply_reference(inst, ref_from, ref_to=None, forward=None, ch_type="auto"):
return inst, ref_data


def _apply_dict_reference(inst, ref_dict):
"""Apply a dict-based custom EEG referencing scheme."""
# Check that ref_dict channel exist in instance:
ref_dict_channels = list(
set(
list(ref_dict.keys())
+ [item for sublist in ref_dict.values() for item in sublist]
qian-chu marked this conversation as resolved.
Show resolved Hide resolved
)
)
assert all([ref_ch in inst.ch_names for ref_ch in ref_dict_channels]), (
"The custom referencing dictionary "
"contains channels which are not in the "
"instance!"
)

# Copy the data instance to use as reference data:
ref_from_data = inst.copy()._data
# Copy the data instance to modify by re-referencing. Only this array is modified, the other remains untouched :
ref_to_data = inst.copy()._data

if len(ref_dict) > 0:
qian-chu marked this conversation as resolved.
Show resolved Hide resolved
# Loop through each channel to re-reference:
for ch in ref_dict.keys():
assert len(ref_dict[ch]) > 0, f"No channel to re-reference ch-{ch}"
# Get indices of the channels to use as reference
ref_from = pick_channels(inst.ch_names, ref_dict[ch], ordered=True)
# Get indice of channel to re.reference:
ref_to = pick_channels(inst.ch_names, ch, ordered=True)
qian-chu marked this conversation as resolved.
Show resolved Hide resolved

# Compute the reference data:
ref_data = ref_from_data[..., ref_from, :].mean(-2, keepdims=True)
# Subtract the reference data to the channel to re-reference:
ref_to_data[..., ref_to, :] -= ref_data
# Add the data back to the instance:
inst._data = ref_to_data
return inst


@fill_doc
def add_reference_channels(inst, ref_channels, copy=True):
"""Add reference channels to data that consists of all zeros.
Expand Down Expand Up @@ -430,7 +468,10 @@ def set_eeg_reference(
"reference."
)

return _apply_reference(inst, ref_channels, ch_sel, forward, ch_type=ch_type)
if ref_channels is dict:
qian-chu marked this conversation as resolved.
Show resolved Hide resolved
return _apply_dict_reference(inst, ref_channels, ch_type=ch_type)
else:
return _apply_reference(inst, ref_channels, ch_sel, forward, ch_type=ch_type)


def _get_ch_type(inst, ch_type):
Expand Down
11 changes: 9 additions & 2 deletions mne/utils/docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3660,13 +3660,20 @@ def _reflow_param_docstring(docstring, has_first_line=True, width=75):
"""

docdict["ref_channels_set_eeg_reference"] = """
ref_channels : list of str | str
ref_channels : list of str | str | dict
Can be:

- The name(s) of the channel(s) used to construct the reference.
- The name(s) of the channel(s) used to construct the reference for
every channel of ``ch_type``.
- ``'average'`` to apply an average reference (default)
- ``'REST'`` to use the Reference Electrode Standardization Technique
infinity reference :footcite:`Yao2001`.
- A dictionary mapping names of channels to be referenced to (a list of)
names of channels to use as reference. This is the most flexible
re-referencing approaching. For example, {'A1': 'A3'} would replace the
data in channel 'A1' with the difference between 'A1' and 'A3'. To take
the average of multiple channels as reference, supply a list of channel
names as the dictionary value, e.g. {'A1': ['A2', 'A3']}.
qian-chu marked this conversation as resolved.
Show resolved Hide resolved
- An empty list, in which case MNE will not attempt any re-referencing of
the data
"""
Expand Down
Loading