Add per-group ref_channel_ids to common_reference#4601
Open
grahamfindlay wants to merge 3 commits into
Open
Conversation
…ncing) With reference="global" + groups, common_reference referenced each group to its OWN channels and ignored ref_channel_ids, despite the docstring stating "a list of channels to be applied to each group is expected". This allows ref_channel_ids to be a list of per-group channel-id lists: the reference subtracted from each group is the operator (median/average) over that group's reference set, which may include channels OUTSIDE the group. This enables cross-group referencing (e.g. each tetrode referenced to the median of all channels on the other tetrodes). ref_channel_ids=None (default) keeps the previous own-group behavior.
The most principled reference for a tetrode may sometimes be the average/median of all OTHER tetrodes. In other words, each group is referenced to all channels NOT in it -- ref_channel_ids is each group's complement (with "global" reference and "groups"). Adds common_reference(..., ref_channel_ids="complement") as syntactic sugar for this.
Member
|
Thanks @grahamfindlay I like the idea, but I would rename it to make it clearer. What about |
Contributor
Author
|
@alejoe91 makes sense, done. Another possibility (my personal fave): def common_reference(
recording: BaseRecording,
reference: Literal["global", "annular", "out_of_group", "ref_channel_ids"] = "global",
operator: Literal["median", "average"] = "median",
groups: list | None = None,
ref_channel_ids: list | int | None = None,
annulus_radius: tuple[float, float] = (30.0, 55.0),
min_annulus_neighbors: int = 5,
dtype: str | np.dtype | None = None,
) -> "CommonReferenceRecording":
"""
Re-references the recording traces: the traces are shifted so that a new zero
(the reference) is subtracted from each channel. The reference can be estimated as a
common median reference (CMR, ``operator="median"``) or common average reference
(CAR, ``operator="average"``).
Parameters
----------
recording : RecordingExtractor
The recording extractor to be re-referenced.
reference : "global" | "annular" | "out_of_group" | "ref_channel_ids", default: "global"
How the reference subtracted from each channel is computed:
* "global" : use all channels as the reference set. With `groups=None`, the `operator`
over every channel is subtracted from every channel (classic CMR/CAR). With `groups`
set, each group is referenced to the `operator` over its own channels (group-wise
CMR/CAR). `ref_channel_ids` must be None. A warning is emitted if any group has fewer
than 16 channels: self-referencing a small group (e.g. a tetrode) subtracts a large
share of the shared neural signal along with the noise. Consider using "out_of_group"
instead for small groups.
* "annular" : local reference — the `operator` over channels within a geometric annulus
around each channel (formerly "local"). The annulus is set by `annulus_radius` and
`min_annulus_neighbors`. Cannot be combined with `groups`; `ref_channel_ids` must be None.
* "out_of_group" : reference each group to all channels NOT in it (its complement / the
out-of-group channels). Requires `groups`; `ref_channel_ids` must be None. This is the
safe choice for small groups, since a group never references itself.
* "ref_channel_ids" : use the channels named in `ref_channel_ids` (required) as the
reference set. With `groups=None`, `ref_channel_ids` is a single channel id or a flat
list of channel ids, and the `operator` over those channels is subtracted from every
channel; a single id (or one-element list) gives a single-channel reference, which
zeros out that channel. With `groups` set, `ref_channel_ids` is a list of lists — one
reference set per group — and each group is referenced to the `operator` over its own
reference set. A group's reference set may include channels outside the group,
enabling cross-group referencing (e.g. each tetrode referenced to channels on the
other tetrodes).
operator : "median" | "average", default: "median"
"median" implements a common median reference (CMR); "average" implements a common
average reference (CAR). Applies to all `reference` modes as the function used to
collapse the reference set to a single trace.
groups : list of lists or None, default: None
Lists of channel ids partitioning the recording into groups (e.g. one list per tetrode
or shank). Referencing is applied independently within each group. Used by "global",
"out_of_group", and "ref_channel_ids"; not allowed with "annular".
ref_channel_ids : list | int | None, default: None
Explicit reference channels for the "ref_channel_ids" mode (required there, must be
None for every other mode). With `groups=None`, a single channel id or a flat list of
channel ids. With `groups` set, a list with one channel-id list per group (same length
and order as `groups`).
annulus_radius : tuple(float, float), default: (30.0, 55.0)
Inner and outer radius (in µm) of the annulus for "annular" reference, as
`(exclude_radius, include_radius)`. Channels closer than the inner radius or farther
than the outer radius are excluded. Setting `(0, include_radius)` yields a circular
local region. Ignored unless `reference="annular"`.
min_annulus_neighbors : int, default: 5
Minimum number of channels in the annulus for "annular" reference. If fewer channels
fall in the annulus, the closest channels beyond the inner radius are used until this
count is reached. Ignored unless `reference="annular"`.
dtype : None or dtype, default: None
If None, the parent recording dtype is kept.
Returns
-------
referenced_recording : CommonReferenceRecording
The lazily re-referenced recording extractor. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
With
reference="global"andgroupspassed (i.e. notNone),common_reference()referenced each group to its own channels and ignoredref_channel_ids. I'm not sure if this was intended behavior or a bug. I think a bug, because the docstring stated "a list of channels to be applied to each group is expected", and I read that as "a list of channels per group to be applied to that group is expected". That would be useful for tetrode recordings, because the most principled reference for a tetrode may sometimes be the average/median of all OTHER tetrodes (i.e., don't subtract the tetrode's average/median from itself -- especially with small numbers of tetrodes, this could be dangerous).Therefore this PR has 2 commits. The second just introduces some convenient syntactic sugar for the functionality provided by the first.
ref_channel_idsto be a list of per-group channel-id lists: the reference subtracted from each group is the operator (median/average) over that group's reference set, which may include channels OUTSIDE the group. This enables cross-group referencing (e.g. each tetrode referenced to the median of all channels on the other tetrodes).ref_channel_ids=None(default) keeps the previous own-group behavior.common_reference(..., ref_channel_ids="complement")as syntacticsugar for referencing each group to all channels NOT in it -- it just auto-builds the correct
ref_channel_idsto accomplish this.So now if you have groups that represent the tetrodes, you can do tetrode-aware referencing with:
or