Alignment Issue When Extracting Epochs with Dynamic Trial Lengths

Hi MNE Community,

I’m working on my master’s thesis where I need to extract epochs with dynamic lengths (based on the participant’s speed to complete the trial). I want to extract segments based on these dynamic trial times. The two types of trials I have are gesture and verbal. They can be either correct or incorrect The (psychopy) markers always appear in the following structure:

start_gesture or start_verbal → end_gesture or end_verbal → result/correct or result/incorrect

I have tried several methods to extract and segment the trials, all failed. When something is extracted, it does not seem to match the trial length at all (See screenshot for example: when i plot a segment, there are markers that only appear in between trials, which makes me think the extracted segment is not the one expected)

Here’s the current approach I am trying:

import mne 
import os

infile = os.path.join("1_data_preprocessed/01A_preprocessed.fif")

raw = mne.io.read_raw(infile, preload=True)
events, event_id = mne.events_from_annotations(raw)

metadata_tmin, metadata_tmax = 0,20.0
row_events = [
    "start_gesture",
    "start_verbal",
]
keep_first = "response"


metadata, events, event_id = mne.epochs.make_metadata(
    events=events,
    event_id=event_id,
    tmin=metadata_tmin,
    tmax=metadata_tmax,
    sfreq=raw.info["sfreq"],
    row_events=row_events,
    keep_first=keep_first,
)


metadata = metadata.rename(columns={"first_response": "result"})
metadata.reset_index(drop=True, inplace=True)
metadata


tmax_values = []

for idx, row in metadata.iterrows():
    if "start_gesture" in row["event_name"]:
        stop_time = row["end_gesture"] 
    if "start_verbal" in row["event_name"]:
            stop_time = row["end_verbal"] 
    tmax = stop_time
    tmax_values.append(tmax)

epochs = []
for i, row in metadata.iterrows():
    tmax = tmax_values[i]
    tmin = 0 
    epoch = mne.Epochs(
        raw=raw,
        events=events,
        event_id=event_id,
        tmin=tmin,
        tmax=tmax,  
        metadata=metadata,
        baseline=None,
        preload=True,
    )
    epochs.append(epoch)
    

output_dir = "extracted_segments"



for i, epoch in enumerate(epochs):
    event_time = events[i][0] / raw.info['sfreq']  
    epoch_start_time = event_time + epoch.times[0]  
    epoch_end_time = event_time + epoch.times[-1]   

    segment = raw.copy().crop(tmin=epoch_start_time, tmax=epoch_end_time)
        output_file = os.path.join(output_dir, f"trial{i}.fif")
    segment.save(output_file, overwrite=True)

   

Issue
Even though I set the tmin and tmax dynamically based on the event markers (start_* and end_*), the resulting epochs seem misaligned.

Could someone help me figure out why the epochs are not aligning correctly? Any suggestions on how to better extract the segmented trials ?

Thank you so much in advance for your help!

Unfortunately, cutting epochs of varying length is not something we support. Since the epochs are stored in a (epochs x channels x times) numpy array, they all need to be of the same length. A possible workaround is to cut them to the maximum length and then later in your analysis cut each individual epoch down to the correct length during further processing. But remember, as long as epochs are inside an mne.Epochs object, they need all be the same length.