mne-tools / mne-tools/mne-python

epochs realignment: shifting time by variable length on each epoch.

Open
#5,794 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
3.5k
Forks
1.6k
Avg merge
1d 6h
Merged PRs (30d)
100

Description

Describe the problem

I have a dataset where subjects listen to a series of 4-5 tones on each trial. However, the Inter Onset Interval between tones is different from trial to trial. I would like to create a function that allows me to realign epochs so that the 0 in epoch.times is now centered on the 2nd, third, final, etc tone. Typically this is done by altering the event array directly. However, because of the series of tones, I still want my baseline to always be before the first tone where there is silence.
So I want to be able to:

  1. define large epochs that cover all tones in each trial
  2. Apply a baseline, timelocked to pre first tone, in an epoch by epoch manner
  3. Realign epochs to a specific tone in the trial. Critically, this shift would be by a different amount for each epoch so epochs.shift_time wouldn't work.
Describe your solution

I have found a solution to do this outside of mne and would like to implement it in a TimeMixin so that it can be used for both Epochs, EpochsTFR and wherever else there are multiple trials with time stored, (Source Estimates?).

It's a bit ugly and hard to follow, which is exactly why I think we should implement it so that it's well tested and users can avoid the potential errors when they try to do it outside of mne. Here is a very basic example which shows the concept of the method.

import numpy as np
t = np.round(np.linspace(-.5, 1., 16), 1)
sfreq = 1. / (t[1] - t[0])
n_epochs = 3
# faux data, 3 epochs x 16 timepoints
data = t * np.ones(n_epochs)[:, None]

# How many samples to shift for each epoch in realignment
sampshift = np.array([2, 4, 6])

# realigned epochs must have smaller window than original epoch
new_tmin, new_tmax = -.2, .3

# indices to extract the correct realigned samples
minsamp = np.round((new_tmin - t[0]) * sfreq).astype(int)
maxsamp = np.round((new_tmax - new_tmin) * sfreq).astype(int) + minsamp
idx = sampshift[:, None] + np.arange(minsamp, maxsamp + 1)

# needs some checks here to make sure you don't exceed epoch size
shift_data = data[np.arange(n_epochs)[:, None], idx]

I would also like to move some methods like .shift_time, maybe .crop into the TimeMixin so that they are not implemented in multiple places. This could be a separate PR.

Describe possible alternatives

Another alternative for my specific problem is to allow for different baseline windows for each epoch but this doesn't seem to me to be a good practice generally and I'm not sure how much we want to encourage people to draw baselines from different timepoints in a typical use case.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the TimeMixin proposal and the existing shift_time and crop behavior on Epochs and EpochsTFR. Use the example's per-epoch sample shifts and baseline requirements to define the API, then determine how Source Estimates or other time-indexed objects fit. Done means variable shifts are safely applied per epoch with bounds checks and tests cover the realignment behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
data
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.