Example #1
0
def split_TFR(
    BIDS_PATH,
    subj,
    bloc,
    by="VTC",
    lobound=None,
    hibound=None,
    stage="1600TFR",
    filt_order=3,
    filt_cutoff=0.05,
):
    if by == "VTC":
        event_id = {"IN": 1, "OUT": 0}
        INidx, OUTidx, VTC_epochs, idx_trimmed = get_VTC_epochs(
            LOGS_DIR,
            subj,
            bloc,
            lobound=lobound,
            hibound=hibound,
            stage=stage[:-3] + "epo",
            save_epochs=False,
            filt_order=filt_order,
            filt_cutoff=filt_cutoff,
        )
        epo_path, epo_filename = get_SAflow_bids(
            BIDS_PATH, subj, bloc, stage=stage[:-3] + "epo", cond=None
        )
        epo_events = mne.read_events(
            epo_filename, verbose=False
        )  # get events from the epochs file (so no resp event)
        TFR_path, TFR_filename = get_SAflow_bids(
            BIDS_PATH, subj, bloc, stage=stage, cond=None
        )
        TFR = mne.time_frequency.read_tfrs(TFR_filename)
        for i, event in enumerate(epo_events):
            if i in INidx:
                TFR[0].events[i, 2] = 1
            if i in OUTidx:
                TFR[0].events[i, 2] = 0
        TFR[0].event_id = event_id
    return TFR
Example #2
0
def load_VTC_data(BIDS_PATH, LOGS_DIR, SUBJ_LIST, BLOCS_LIST):
    VTC_alldata = []
    for subj in SUBJ_LIST:
        all_subj = []  ## all the data of one subject
        for run in BLOCS_LIST:
            # get events from epochs file
            epo_path, epo_filename = get_SAflow_bids(
                BIDS_PATH, subj, run, "epo", cond=None
            )
            events_epoched = mne.read_events(
                epo_filename, verbose=False
            )  # get events from the epochs file (so no resp event)
            # get events from original file (only 599 events)
            events_fname, events_fpath = get_SAflow_bids(
                BIDS_PATH, subj, run, stage="preproc_raw", cond=None
            )
            raw = read_raw_fif(
                events_fpath, preload=False, verbose=False
            )  # , min_duration=2/epochs.info['sfreq'])
            all_events = mne.find_events(
                raw, min_duration=2 / raw.info["sfreq"], verbose=False
            )
            stim_idx = []
            for i in range(len(all_events)):
                if all_events[i, 2] in [21, 31]:
                    stim_idx.append(i)
            all_events = all_events[stim_idx]
            # compute VTC for all trials
            log_file = find_logfile(subj, run, os.listdir(LOGS_DIR))
            VTC, INbounds, OUTbounds, INzone, OUTzone = get_VTC_from_file(
                LOGS_DIR + log_file, lobound=None, hibound=None
            )
            epochs_VTC = []
            for event_time in events_epoched[:, 0]:
                idx = list(all_events[:, 0]).index(event_time)
                epochs_VTC.append(VTC[idx])
            all_subj.append(np.array(epochs_VTC))
        VTC_alldata.append(all_subj)
    return VTC_alldata
Example #3
0
def load_PSD_data(BIDS_PATH, SUBJ_LIST, BLOCS_LIST, time_avg=True, stage="PSD"):
    """
    Returns a list containing n_subj lists of n_blocs matrices of shape n_freqs X n_channels X n_trials
    """
    PSD_alldata = []
    for subj in SUBJ_LIST:
        all_subj = []  ## all the data of one subject
        for run in BLOCS_LIST:
            SAflow_bidsname, SAflow_bidspath = get_SAflow_bids(
                BIDS_PATH, subj, run, stage=stage, cond=None
            )
            mat = loadmat(SAflow_bidspath)["PSD"]
            if time_avg == True:
                mat = np.mean(mat, axis=2)  # average PSDs in time across epochs
            all_subj.append(mat)
        PSD_alldata.append(all_subj)
    return PSD_alldata
Example #4
0
def new_split_trials(subj, run, by="VTC", inout_bounds=None):
    condA = []
    condB = []
    if by == "odd":
        cond = "5050"
    elif by == "VTC" or by == "VTCprec":
        cond = f"{inout_bounds[0]}{inout_bounds[1]}"
    for idx_freq, freq_bounds in enumerate(FREQS):
        _, PSDpath = get_SAflow_bids(
            BIDS_PATH,
            subj,
            run,
            stage=f"-epoenv4001200_{FREQS_NAMES[idx_freq]}",
            cond=cond,
        )

        epochs = mne.read_epochs(PSDpath)
        if by == "VTC":
            condA_epochs = epochs["FreqIN"]
            condB_epochs = epochs["FreqOUT"]
        elif by == "VTCprec":
            epochs_prec = annotate_precursor_events(BIDS_PATH, subj, run)
            epochs.events = epochs_prec.events
            epochs.event_id = epochs_prec.event_id
            condA_epochs = epochs["FreqIN"]
            condB_epochs = epochs["FreqOUT"]
        elif by == "odd":
            condA_epochs = epochs[["FreqIN", "FreqOUT", "FreqHit"]]
            condB_epochs = epochs["RareHit"]
        condA.append(condA_epochs.get_data())
        condB.append(condB_epochs.get_data())
    try:
        print(np.array(condA).shape)
        print(np.array(condB).shape)
        condA = np.mean(np.array(condA), axis=3).transpose(1, 2, 0)
        condB = np.mean(np.array(condB), axis=3).transpose(1, 2, 0)
    except:
        breakpoint()
    return condA, condB
Example #5
0
def annotate_precursor_events(BIDS_PATH, subj, bloc):

    _, epopath = get_SAflow_bids(BIDS_PATH,
                                 subj,
                                 bloc,
                                 stage="-epo4001200",
                                 cond=None)
    epochs = mne.read_epochs(epopath)
    # find events
    events = epochs.events
    files_list = os.listdir(LOGS_DIR)
    logfile = LOGS_DIR + find_logfile(subj, bloc, files_list)
    (
        IN_idx,
        OUT_idx,
        VTC_raw,
        VTC_filtered,
        IN_mask,
        OUT_mask,
        performance_dict,
        df_response,
        RT_to_VTC,
    ) = get_VTC_from_file(subj, bloc, files_list, inout_bounds=[50, 50])
    events = annotate_events(logfile, events, inout_idx=[IN_idx, OUT_idx])
    event_id = get_present_events(events)

    events_precursor = []
    for idx, ev in enumerate(events):
        if ev[2] == 310:
            if events[idx - 1][2] == 2111 or events[idx - 1][2] == 2110:
                events_precursor.append(events[idx - 1])
    events_precursor = np.array(events_precursor)

    epochs.events = events_precursor
    epochs.event_id = event_id
    return epochs
Example #6
0
        for run in BLOCS_LIST:
            CONDS_LIST = args.split
            by = args.by
            stage = args.input_stage

            if by == "VTC":
                INepochs, OUTepochs = new_split_trials(subj=subj,
                                                       run=run,
                                                       by="VTC",
                                                       inout_bounds=CONDS_LIST)
                precINepochs, precOUTepochs = new_split_trials(
                    subj=subj, run=run, by="VTCprec", inout_bounds=CONDS_LIST)
                VTCepochs_path, VTCepochs_filename = get_SAflow_bids(
                    BIDS_PATH,
                    subj=subj,
                    run=run,
                    stage=stage,
                    cond=f"{CONDS_LIST[0]}{CONDS_LIST[1]}",
                )
                INepochs_path, INepochs_filename = get_SAflow_bids(
                    BIDS_PATH,
                    subj=subj,
                    run=run,
                    stage=stage,
                    cond="IN{}".format(CONDS_LIST[0]),
                )
                OUTepochs_path, OUTepochs_filename = get_SAflow_bids(
                    BIDS_PATH,
                    subj=subj,
                    run=run,
                    stage=stage,
Example #7
0
from saflow.neuro import saflow_preproc, find_rawfile
from saflow import BIDS_PATH, SUBJ_LIST, BLOCS_LIST
import argparse

parser = argparse.ArgumentParser()
parser.add_argument(
    "-s",
    "--subject",
    default='04',
    type=str,
    help="Subject to process",
)
parser.add_argument(
	"-i",
	"--ica",
	default = True,
	type = bool,
	help="Preprocessing with or without ica"
)
args = parser.parse_args()

if __name__ == "__main__":
	#for subj in SUBJ_LIST:
	subj = args.subject
	ica = args.ica
	for bloc in BLOCS_LIST:
		file_path = get_SAflow_bids(BIDS_PATH, subj=subj, run=bloc, stage='raw_ds')[1]
		save_path = get_SAflow_bids(BIDS_PATH, subj=subj, run=bloc, stage='preproc_raw')[1]
		report_path = get_SAflow_bids(BIDS_PATH, subj=subj, run=bloc, stage='preproc_report')[1]
		saflow_preproc(file_path, save_path, report_path, ica=ica)
Example #8
0
parser = argparse.ArgumentParser()
parser.add_argument(
    "-s",
    "--subject",
    default="04",
    type=str,
    help="Subject to process",
)
args = parser.parse_args()

if __name__ == "__main__":
    subj = args.subject
    for bloc in BLOCS_LIST:
        preproc_path, preproc_filename = get_SAflow_bids(BIDS_PATH,
                                                         subj,
                                                         bloc,
                                                         stage="preproc_raw",
                                                         cond=None)
        epoched_path, epoched_filename = get_SAflow_bids(BIDS_PATH,
                                                         subj,
                                                         bloc,
                                                         stage="-epo4001200",
                                                         cond=None)
        ARlog_path, ARlog_filename = get_SAflow_bids(BIDS_PATH,
                                                     subj,
                                                     bloc,
                                                     stage="ARlog4001200",
                                                     cond=None)
        if not os.path.isfile(epoched_filename):
            epochs_clean, AR_log = segment_files(preproc_filename,
                                                 tmin=0.4,
Example #9
0
    type=str,
    help="Subject to process",
)

args = parser.parse_args()

### OPEN SEGMENTED FILES AND COMPUTE PSDS
if __name__ == "__main__":
    subj = args.subject
    tmin = 0.4
    tmax = 1.2
    for bloc in BLOCS_LIST:
        # Generate filenames
        _, epopath = get_SAflow_bids(BIDS_PATH,
                                     subj,
                                     bloc,
                                     stage="-epo4001200",
                                     cond=None)
        _, rawpath = get_SAflow_bids(BIDS_PATH,
                                     subj,
                                     bloc,
                                     stage="preproc_raw",
                                     cond=None)
        _, ARpath = get_SAflow_bids(BIDS_PATH,
                                    subj,
                                    bloc,
                                    stage="ARlog4001200",
                                    cond=None)
        _, PSDpath = get_SAflow_bids(BIDS_PATH,
                                     subj,
                                     bloc,
Example #10
0
        # Correction for multiple comparisons
        # freq_perms = list(itertools.chain.from_iterable(allchans_accperms))
        toplot_featimp = features_importances_list
        figpath_featimp = IMG_DIR + classif_name + "_features_importances" + ".png"

        freq_titles = []
        for idx_pval, pval in enumerate(pvals_list):
            if pval < alpha:
                freq_titles.append(FREQS_NAMES[idx_pval] + " *")
            else:
                freq_titles.append(FREQS_NAMES[idx_pval])

        titles = freq_titles

    _, data_fname = get_SAflow_bids(BIDS_PATH,
                                    subj="04",
                                    run="2",
                                    stage="-epo")
    epochs = mne.read_epochs(data_fname)
    ch_xy = epochs.pick_types(
        meg=True, ref_meg=False).info  # Find the channel's position

    if "singlefeat" in classif_name:
        # Setup the min and max value of the color scale
        vmax_pval = np.max(np.max(np.asarray(toplot_pval)))
        vmin_pval = np.min(np.min(np.asarray(toplot_pval)))
        vmax_acc = np.max(np.max(np.asarray(toplot_acc)))
        vmin_acc = np.min(np.min(np.asarray(toplot_acc)))

        array_topoplot(
            toplot_pval,
            ch_xy,
Example #11
0
def prepare_data(
    BIDS_PATH,
    SUBJ_LIST,
    BLOCS_LIST,
    conds_list,
    stage="PSD",
    CHAN=0,
    FREQ=None,
    balance=False,
    avg=False,
    level="group",
):
    # Prepare data
    print("Prepping data :")
    print("=====SUBJ=======")
    print(f"{SUBJ_LIST}")
    print("=====BLOCS=======")
    print(f"{BLOCS_LIST}")
    print("=====FREQ=======")
    print(f"{FREQ}")
    print("=====CHAN=======")
    print(f"{CHAN}")
    print("============")

    X = []
    y = []
    groups = []
    for i_subj, subj in enumerate(SUBJ_LIST):
        for i_cond, cond in enumerate(conds_list):
            X_subj = []
            for i_run, run in enumerate(BLOCS_LIST):
                _, fpath_cond = get_SAflow_bids(BIDS_PATH,
                                                subj,
                                                run,
                                                stage=stage,
                                                cond=cond)
                with open(fpath_cond, "rb") as f:
                    data = pickle.load(f)
                if avg:
                    X_subj.append(np.mean(data[:, CHAN, FREQ], axis=0))
                else:
                    for x in data[:, CHAN, FREQ]:
                        X.append(x)
                        y.append(i_cond)
                        if level == "group":
                            groups.append(i_subj)
                        elif level == "subject":
                            groups.append(i_run)
            if avg:
                X.append(np.mean(np.array(X_subj), axis=0))
                y.append(i_cond)
                groups.append(i_subj)
    if balance:
        X, y, groups = balance_data(X, y, groups)

    if type(CHAN) is int and type(FREQ) is int:
        X = np.array(X).reshape(-1, 1)
    elif len(CHAN) != 1:  #
        X = np.array(X).reshape(-1, len(X[0]))  # ??
    y = np.asarray(y)
    groups = np.asarray(groups)
    return X, y, groups
Example #12
0
def split_trials(
    BIDS_PATH,
    LOGS_DIR,
    subj,
    run,
    stage="PSD",
    by="VTC",
    keep_errors=False,
    equalize=False,
    lobound=None,
    hibound=None,
    filt_order=3,
    filt_cutoff=0.05,
    freq_names=None,
    oddball="hits",
):
    """
    If stage is 'env', freq_names must be specified.
    """
    # Split epochs indices
    if by == "VTC":
        INidx, OUTidx, VTC_epochs, idx_trimmed = get_VTC_epochs(
            BIDS_PATH,
            LOGS_DIR,
            subj,
            run,
            lobound=lobound,
            hibound=hibound,
            save_epochs=False,
            filt_order=filt_order,
            filt_cutoff=filt_cutoff,
        )
        condA_idx = INidx
        condB_idx = OUTidx
        print("{} IN epochs".format(len(INidx)))
        print("{} OUT epochs".format(len(OUTidx)))
    elif by == "odd":
        freqs_hits_idx, freqs_miss_idx, rares_hits_idx, rares_miss_idx = get_odd_epochs(
            BIDS_PATH, LOGS_DIR, subj, run, stage="-epo"
        )
        if oddball == "all":
            condA_idx = np.sort(np.concatenate((freqs_hits_idx, freqs_miss_idx)))
            condB_idx = np.sort(np.concatenate((rares_hits_idx, rares_miss_idx)))
        elif oddball == "hits":
            condA_idx = freqs_hits_idx
            condB_idx = rares_hits_idx
        elif oddball == "miss":
            condA_idx = freqs_miss_idx
            condB_idx = rares_miss_idx
        elif oddball == "rares":
            condA_idx = rares_hits_idx
            condB_idx = rares_miss_idx
        print("{} condA epochs".format(len(condA_idx)))
        print("{} condB epochs".format(len(condB_idx)))
    elif by == "resp":
        freqs_hits_idx, freqs_miss_idx, rares_hits_idx, rares_miss_idx = get_odd_epochs(
            BIDS_PATH, LOGS_DIR, subj, run, stage="-epo"
        )
        condA_idx = np.sort(np.concatenate((freqs_hits_idx, rares_miss_idx)))
        condB_idx = np.sort(np.concatenate((freqs_miss_idx, rares_hits_idx)))
        print("{} Resp epochs".format(len(condA_idx)))
        print("{} NoResp epochs".format(len(condB_idx)))
        condA_idx = [int(x) for x in condA_idx]
        condB_idx = [int(x) for x in condB_idx]
    # Load epochs
    if stage == "PSD":
        fname, fpath = get_SAflow_bids(BIDS_PATH, subj, run, stage, cond=None)
        with open(fpath, "rb") as f:
            data = pickle.load(f)
        try:
            condA = data[condA_idx]
            condB = data[condB_idx]
        except IndexError:
            print("condB empty")
            condB = []
    elif "env" in stage:
        condA = []
        condB = []
        for freq in freq_names:
            fname, fpath = get_SAflow_bids(BIDS_PATH, subj, run, stage, cond=freq)
            data = mne.read_epochs(fpath)
            condA.append(data[condA_idx])
            condB.append(data[condB_idx])
    return condA, condB
Example #13
0
def split_PSD_data(
    BIDS_PATH,
    SUBJ_LIST,
    BLOCS_LIST,
    by="VTC",
    lobound=None,
    hibound=None,
    stage="PSD",
    filt_order=3,
    filt_cutoff=0.1,
):
    """
    This func splits the PSD data into two conditions. It returns a list of 2 (cond1 and cond2), each containing a list of n_subject matrices of shape n_freqs X n_channels X n_trials
    """
    PSD_alldata = load_PSD_data(
        BIDS_PATH, SUBJ_LIST, BLOCS_LIST, time_avg=True, stage=stage
    )
    PSD_cond1 = []
    PSD_cond2 = []
    for subj_idx, subj in enumerate(SUBJ_LIST):
        subj_cond1 = []
        subj_cond2 = []
        for bloc_idx, bloc in enumerate(BLOCS_LIST):
            print("Splitting sub-{}_run-{}".format(subj, bloc))

            # Obtain indices of the two conditions
            if by == "VTC":
                INidx, OUTidx, VTC_epochs, idx_trimmed = get_VTC_epochs(
                    LOGS_DIR,
                    subj,
                    bloc,
                    lobound=lobound,
                    hibound=hibound,
                    save_epochs=False,
                    filt_order=filt_order,
                    filt_cutoff=filt_cutoff,
                )
                cond1_idx = INidx
                cond2_idx = OUTidx
            if by == "odd":
                # Get indices of freq and rare events
                ev_fname, ev_fpath = get_SAflow_bids(BIDS_PATH, subj, bloc, stage="epo")
                events_artrej = mne.read_events(ev_fpath)
                log_file = LOGS_DIR + find_logfile(subj, bloc, os.listdir(LOGS_DIR))
                events_fname, events_fpath = get_SAflow_bids(
                    BIDS_PATH, subj, bloc, stage="preproc_raw", cond=None
                )
                raw = read_raw_fif(
                    events_fpath, preload=False, verbose=False
                )  # , min_duration=2/epochs.info['sfreq'])
                try:
                    events = mne.find_events(
                        raw, min_duration=1 / raw.info["sfreq"], verbose=False
                    )
                except ValueError:
                    events = mne.find_events(
                        raw, min_duration=2 / raw.info["sfreq"], verbose=False
                    )

                events_noerr, events_comerr, events_omerr = remove_errors(
                    log_file, events
                )
                events_trimmed, idx_trimmed = trim_events(events_noerr, events_artrej)
                cond1_idx = []
                cond2_idx = []
                for idx, ev in enumerate(events_trimmed):
                    if ev[2] == 21:  # Frequent events
                        cond1_idx.append(idx)
                    if ev[2] == 31:
                        cond2_idx.append(idx)
                cond1_idx = np.array(cond1_idx)
                cond2_idx = np.array(cond2_idx)
                # Add this to keep the same number of trials in both conditions
                random.seed(0)
                cond1_idx = random.choices(cond1_idx, k=len(cond2_idx))
                print(
                    "N trials retained for each condition : {}".format(len(cond2_idx))
                )
            # Pick the data of each condition
            if bloc_idx == 0:  # if first bloc, init ndarray size using the first matrix
                subj_cond1 = PSD_alldata[subj_idx][bloc_idx][:, :, cond1_idx]
                subj_cond2 = PSD_alldata[subj_idx][bloc_idx][:, :, cond2_idx]
            else:  # if not first bloc, just concatenate along the trials dimension
                subj_cond1 = np.concatenate(
                    (subj_cond1, PSD_alldata[subj_idx][bloc_idx][:, :, cond1_idx]),
                    axis=2,
                )
                subj_cond2 = np.concatenate(
                    (subj_cond2, PSD_alldata[subj_idx][bloc_idx][:, :, cond2_idx]),
                    axis=2,
                )
        PSD_cond1.append(subj_cond1)
        PSD_cond2.append(subj_cond2)
    splitted_PSD = [PSD_cond1, PSD_cond2]
    return splitted_PSD
Example #14
0
def get_VTC_epochs(
    BIDS_PATH,
    LOGS_DIR,
    subj,
    run,
    stage="-epo",
    lobound=None,
    hibound=None,
    save_epochs=False,
    filt_order=3,
    filt_cutoff=0.1,
):
    """
    This functions allows to use the logfile to split the epochs obtained in the epo.fif file.
    It works by comparing the timestamps of IN and OUT events to the timestamps in the epo file events
    It returns IN and OUT indices that are to be used in the split_PSD_data function

    """
    ### Get events after artifact rejection have been performed
    epo_path, epo_filename = get_SAflow_bids(
        BIDS_PATH, subj, run, stage=stage, cond=None
    )
    events_artrej = mne.read_events(
        epo_filename, verbose=False
    )  # get events from the epochs file (so no resp event)

    ### Find logfile to extract VTC
    behav_list = os.listdir(LOGS_DIR)
    log_file = LOGS_DIR + find_logfile(subj, run, behav_list)

    (
        INidx,
        OUTidx,
        VTC_raw,
        VTC_filtered,
        IN_mask,
        OUT_mask,
        performance_dict,
        df_response_out,
    ) = get_VTC_from_file(
        subj, run, behav_list, inout_bounds=[lobound, hibound], filt_cutoff=filt_cutoff
    )

    ### Get original events and split them using the VTC
    events_fname, events_fpath = get_SAflow_bids(
        BIDS_PATH, subj, run, stage="preproc_raw", cond=None
    )
    raw = read_raw_fif(
        events_fpath, preload=False, verbose=False
    )  # , min_duration=2/epochs.info['sfreq'])
    try:
        events = mne.find_events(raw, min_duration=1 / raw.info["sfreq"], verbose=False)
    except ValueError:
        events = mne.find_events(raw, min_duration=2 / raw.info["sfreq"], verbose=False)

    (
        events_noerr,
        events_comerr,
        events_omerr,
        events_comcorr,
        events_omcorr,
    ) = remove_errors(log_file, events)
    # Keep only events that are correct and clean
    events_trimmed, idx_trimmed = trim_events(events_comcorr, events_artrej)
    # Write INidx and OUTidx as indices of clean events
    INidx, OUTidx = trim_INOUT_idx(INidx, OUTidx, events_trimmed, events)

    VTC_epo = np.array([VTC_raw[idx] for idx in idx_trimmed])

    return INidx, OUTidx, VTC_epo, idx_trimmed
Example #15
0
def get_odd_epochs(BIDS_PATH, LOGS_DIR, subj, bloc, stage="-epo"):
    """
    Returns an array of indices of Freqs and Rares epochs. Retains only clean epochs.
    """
    ### Get events after artifact rejection have been performed
    epo_path, epo_filename = get_SAflow_bids(
        BIDS_PATH, subj, bloc, stage=stage, cond=None
    )
    events_artrej = mne.read_events(
        epo_filename, verbose=False
    )  # get events from the epochs file (so no resp event)

    ### Get original events from the raw file, to compare them to the events left in the epochs file
    events_fname, events_fpath = get_SAflow_bids(
        BIDS_PATH, subj, bloc, stage="preproc_raw", cond=None
    )
    raw = read_raw_fif(
        events_fpath, preload=False, verbose=False
    )  # , min_duration=2/epochs.info['sfreq'])
    try:
        events = mne.find_events(raw, min_duration=1 / raw.info["sfreq"], verbose=False)
    except ValueError:
        events = mne.find_events(raw, min_duration=2 / raw.info["sfreq"], verbose=False)

    # Get the list of hits/miss events
    log_file = LOGS_DIR + find_logfile(subj, bloc, os.listdir(LOGS_DIR))
    (
        events_noerr,
        events_comerr,
        events_omerr,
        events_comcorr,
        events_omcorr,
    ) = remove_errors(log_file, events)

    # Keep only events that are clean, and split them by condition
    # Start with correct events
    events_noerr_trimmed, idx_noerr_trimmed = trim_events(events_noerr, events_artrej)
    freqs_hits_idx = np.array(
        [idx_noerr_trimmed[i] for i, x in enumerate(events_noerr_trimmed) if x[2] == 21]
    )
    rares_hits_idx = np.array(
        [idx_noerr_trimmed[i] for i, x in enumerate(events_noerr_trimmed) if x[2] == 31]
    )

    # Then commission errors
    if events_comerr.size > 0:
        events_comerr_trimmed, idx_comerr_trimmed = trim_events(
            events_comerr, events_artrej
        )
        rares_miss_idx = np.array(idx_comerr_trimmed)
    else:
        rares_miss_idx = np.array([])
    # And finally ommission errors
    if events_omerr.size > 0:
        events_omerr_trimmed, idx_omerr_trimmed = trim_events(
            events_omerr, events_artrej
        )
        freqs_miss_idx = np.array(idx_omerr_trimmed)
    else:
        freqs_miss_idx = np.array([])

    return freqs_hits_idx, freqs_miss_idx, rares_hits_idx, rares_miss_idx