예제 #1
0
def _create_cnt_y_and_trial_bounds_from_start_and_ival(n_samples, events, fs,
                                                       name_to_start_codes,
                                                       epoch_ival_ms):
    ival_in_samples = ms_to_samples(np.array(epoch_ival_ms), fs)
    start_offset = np.int32(np.round(ival_in_samples[0]))
    # we will use ceil but exclusive...
    stop_offset = np.int32(np.ceil(ival_in_samples[1]))
    mrk_code_to_name_and_y = _to_mrk_code_to_name_and_y(name_to_start_codes)
    class_to_n_trials = Counter()
    n_classes = len(name_to_start_codes)
    cnt_y = np.zeros((n_samples, n_classes), dtype=np.int64)
    i_start_stops = []
    for i_sample, mrk_code in zip(events[:, 0], events[:, 1]):
        start_sample = int(i_sample) + start_offset
        stop_sample = int(i_sample) + stop_offset
        if mrk_code in mrk_code_to_name_and_y:
            if start_sample < 0:
                log.warning(
                    "Ignore trial with marker code {:d}, would start at "
                    "sample {:d}".format(mrk_code, start_sample))
                continue
            if stop_sample > n_samples:
                log.warning("Ignore trial with marker code {:d}, would end at "
                            "sample {:d} of {:d}".format(
                                mrk_code, stop_sample - 1, n_samples - 1))
                continue

            name, this_y = mrk_code_to_name_and_y[mrk_code]
            i_start_stops.append((start_sample, stop_sample))
            cnt_y[start_sample:stop_sample, this_y] = 1
            class_to_n_trials[name] += 1
    log.info("Trial per class:\n{:s}".format(str(class_to_n_trials)))
    return cnt_y, i_start_stops
예제 #2
0
def _create_signal_target_from_start_and_ival(data, events, fs, name_to_codes,
                                              epoch_ival_ms):
    ival_in_samples = ms_to_samples(np.array(epoch_ival_ms), fs)
    start_offset = np.int32(np.round(ival_in_samples[0]))
    # we will use ceil but exclusive...
    stop_offset = np.int32(np.ceil(ival_in_samples[1]))
    mrk_code_to_name_and_y = _to_mrk_code_to_name_and_y(name_to_codes)

    class_to_n_trials = Counter()
    X = []
    y = []

    for i_sample, mrk_code in zip(events[:, 0], events[:, 1]):
        start_sample = int(i_sample) + start_offset
        stop_sample = int(i_sample) + stop_offset
        if mrk_code in mrk_code_to_name_and_y:
            name, this_y = mrk_code_to_name_and_y[mrk_code]
            X.append(data[:, start_sample:stop_sample].astype(np.float32))
            y.append(np.int64(this_y))
            class_to_n_trials[name] += 1
    log.info("Trial per class:\n{:s}".format(str(class_to_n_trials)))
    return SignalAndTarget(np.array(X), np.array(y))
예제 #3
0
def add_breaks(events,
               fs,
               break_start_code,
               break_stop_code,
               name_to_start_codes,
               name_to_stop_codes,
               min_break_length_ms=None,
               max_break_length_ms=None,
               break_start_offset_ms=None,
               break_stop_offset_ms=None):
    """
    Add break events to given events.

    Parameters
    ----------
    events: 2d-array
        Dimensions: Number of events, 2. For each event, should contain sample
        index and marker code.
    fs: number
        Sampling rate.
    break_start_code: int
        Marker code that will be used for break start markers.
    break_stop_code: int
        Marker code that will be used for break stop markers.
    name_to_start_codes: OrderedDict (str -> int or list of int)
        Ordered dictionary mapping class names to start marker code or 
        start marker codes.
    name_to_stop_codes: dict (str -> int or list of int), optional
        Dictionary mapping class names to stop marker code or stop marker codes.
    min_break_length_ms: number, optional
        Minimum length in milliseconds a break should have to be included.
    max_break_length_ms: number, optional
        Maximum length in milliseconds a break can have to be included.
    break_start_offset_ms: number, optional
        What offset from trial end to start of the break in ms.
    break_stop_offset_ms: number, optional
        What offset from next trial start end to previous break end in ms.

    Returns
    -------
    events: 2d-array
        Events with break start and stop markers.
    """
    min_samples = (None if min_break_length_ms is None else ms_to_samples(
        min_break_length_ms, fs))
    max_samples = (None if max_break_length_ms is None else ms_to_samples(
        max_break_length_ms, fs))
    orig_events = events
    break_starts, break_stops = _extract_break_start_stop_ms(
        events, name_to_start_codes, name_to_stop_codes)

    break_durations = break_stops - break_starts
    valid_mask = np.array([True] * len(break_starts))
    if min_samples is not None:
        valid_mask[break_durations < min_samples] = False
    if max_samples is not None:
        valid_mask[break_durations > max_samples] = False
    if sum(valid_mask) == 0:
        return deepcopy(events)
    break_starts = break_starts[valid_mask]
    break_stops = break_stops[valid_mask]
    if break_start_offset_ms is not None:
        break_starts += int(round(ms_to_samples(break_start_offset_ms, fs)))
    if break_stop_offset_ms is not None:
        break_stops += int(round(ms_to_samples(break_stop_offset_ms, fs)))
    break_events = np.zeros((len(break_starts) * 2, 2))
    break_events[0::2, 0] = break_starts
    break_events[1::2, 0] = break_stops
    break_events[0::2, 1] = break_start_code
    break_events[1::2, 1] = break_stop_code

    new_events = np.concatenate((orig_events, break_events))
    # sort events
    sort_order = np.argsort(new_events[:, 0], kind='mergesort')
    new_events = new_events[sort_order]
    return new_events
예제 #4
0
def _create_cnt_y_and_trial_bounds_from_start_stop(n_samples, events, fs,
                                                   name_to_start_codes,
                                                   epoch_ival_ms,
                                                   name_to_stop_codes):
    """
    Create a one-hot-encoded continuous marker array (cnt_y).
    
    Parameters
    ----------
    n_samples: int
        Number of samples=timesteps in the recorded data.
    events: 2d-array
        Dimensions: Number of events, 2. For each event, should contain sample
        index and marker code.
    fs: number
        Sampling rate.
    name_to_start_codes: OrderedDict (str -> int or list of int)
        Ordered dictionary mapping class names to marker code or marker codes.
        y-labels will be assigned in increasing key order, i.e.
        first classname gets y-value 0, second classname y-value 1, etc.
    epoch_ival_ms: iterable of (int,int)
        Epoching interval in milliseconds. In case only `name_to_codes` given,
        represents start offset and stop offset from start markers. In case
        `name_to_stop_codes` given, represents offset from start marker
        and offset from stop marker. E.g. [500, -500] would mean 500ms
        after the start marker until 500 ms before the stop marker.
    name_to_stop_codes: dict (str -> int or list of int), optional
        Dictionary mapping class names to stop marker code or stop marker codes.
        Order does not matter, dictionary should contain each class in
        `name_to_codes` dictionary.

    Returns
    -------
    cnt_y: 2d-array
        Timeseries of one-hot-labels, time x classes.
    trial_bounds: list of (int,int)
        List of (trial_start, trial_stop) tuples.


    """
    assert np.array_equal(list(name_to_start_codes.keys()),
                          list(name_to_stop_codes.keys()))
    events = np.asarray(events)
    ival_in_samples = ms_to_samples(np.array(epoch_ival_ms), fs)
    start_offset = np.int32(np.round(ival_in_samples[0]))
    # we will use ceil but exclusive...
    stop_offset = np.int32(np.ceil(ival_in_samples[1]))
    start_code_to_name_and_y = _to_mrk_code_to_name_and_y(name_to_start_codes)
    # Ensure all stop marker codes are iterables
    for name in name_to_stop_codes:
        codes = name_to_stop_codes[name]
        if not hasattr(codes, '__len__'):
            name_to_stop_codes[name] = [codes]
    all_stop_codes = np.concatenate(list(name_to_stop_codes.values())).astype(
        np.int64)
    class_to_n_trials = Counter()
    n_classes = len(name_to_start_codes)
    cnt_y = np.zeros((n_samples, n_classes), dtype=np.int64)

    event_samples = events[:, 0]
    event_codes = events[:, 1]
    i_start_stops = []
    i_event = 0
    first_start_code_found = False
    while i_event < len(events):
        while i_event < len(events) and (event_codes[i_event]
                                         not in start_code_to_name_and_y):
            i_event += 1
        if i_event < len(events):
            start_sample = event_samples[i_event]
            start_code = event_codes[i_event]
            start_name = start_code_to_name_and_y[start_code][0]
            start_y = start_code_to_name_and_y[start_code][1]
            i_event += 1
            first_start_code_found = True
            waiting_for_end_code = True

            while i_event < len(events) and (event_codes[i_event]
                                             not in all_stop_codes):
                if event_codes[i_event] in start_code_to_name_and_y:
                    log.warning(
                        "New start marker  {:.0f} at {:.0f} samples found, "
                        "no end marker for earlier start marker {:.0f} "
                        "at {:.0f} samples found.".format(
                            event_codes[i_event], event_samples[i_event],
                            start_code, start_sample))
                    start_sample = event_samples[i_event]
                    start_name = start_code_to_name_and_y[start_code][0]
                    start_code = event_codes[i_event]
                    start_y = start_code_to_name_and_y[start_code][1]
                i_event += 1
        if i_event == len(events):
            if waiting_for_end_code:
                log.warning(
                    ("No end marker for start marker code {:.0f} "
                     "at sample {:.0f} found.").format(start_code,
                                                       start_sample))
            elif (not first_start_code_found):
                log.warning("No markers found at all.")
            break
        stop_sample = event_samples[i_event]
        stop_code = event_codes[i_event]
        assert stop_code in name_to_stop_codes[start_name]
        i_start = int(start_sample) + start_offset
        i_stop = int(stop_sample) + stop_offset
        cnt_y[i_start:i_stop, start_y] = 1
        i_start_stops.append((i_start, i_stop))
        class_to_n_trials[start_name] += 1
        waiting_for_end_code = False

    log.info("Trial per class:\n{:s}".format(str(class_to_n_trials)))
    return cnt_y, i_start_stops
예제 #5
0
def _create_signal_target_from_start_and_stop(data, events, fs,
                                              name_to_start_codes,
                                              epoch_ival_ms,
                                              name_to_stop_codes):
    assert np.array_equal(list(name_to_start_codes.keys()),
                          list(name_to_stop_codes.keys()))
    ival_in_samples = ms_to_samples(np.array(epoch_ival_ms), fs)
    start_offset = np.int32(np.round(ival_in_samples[0]))
    # we will use ceil but exclusive...
    stop_offset = np.int32(np.ceil(ival_in_samples[1]))
    start_code_to_name_and_y = _to_mrk_code_to_name_and_y(name_to_start_codes)
    # Ensure all stop marker codes are iterables
    for name in name_to_stop_codes:
        codes = name_to_stop_codes[name]
        if not hasattr(codes, '__len__'):
            name_to_stop_codes[name] = [codes]
    all_stop_codes = np.concatenate(list(name_to_stop_codes.values()))
    class_to_n_trials = Counter()
    X = []
    y = []

    event_samples = events[:, 0]
    event_codes = events[:, 1]

    i_event = 0
    while i_event < len(events):
        while i_event < len(events) and (event_codes[i_event]
                                         not in start_code_to_name_and_y):
            i_event += 1
        if i_event < len(events):
            start_sample = event_samples[i_event]
            start_code = event_codes[i_event]
            start_name = start_code_to_name_and_y[start_code][0]
            start_y = start_code_to_name_and_y[start_code][1]
            i_event += 1

            while i_event < len(events) and (event_codes[i_event]
                                             not in all_stop_codes):
                if event_codes[i_event] in start_code_to_name_and_y:
                    log.warning(
                        "New start marker  {:.0f} at {:.0f} samples found, "
                        "no end marker for earlier start marker {:.0f} "
                        "at {:.0f} samples found.".format(
                            event_codes[i_event], event_samples[i_event],
                            start_code, start_sample))
                    start_sample = event_samples[i_event]
                    start_name = start_code_to_name_and_y[start_code][0]
                    start_code = event_codes[i_event]
                    start_y = start_code_to_name_and_y[start_code][1]
                i_event += 1
        if i_event == len(events):
            log.warning(
                ("No end marker for start marker code {:.0f} "
                 "at sample {:.0f} found.").format(start_code, start_sample))
            break
        stop_sample = event_samples[i_event]
        stop_code = event_codes[i_event]
        assert stop_code in name_to_stop_codes[start_name]
        i_start = int(start_sample) + start_offset
        i_stop = int(stop_sample) + stop_offset
        X.append(data[:, i_start:i_stop].astype(np.float32))
        y.append(np.int64(start_y))
        class_to_n_trials[start_name] += 1

    log.info("Trial per class:\n{:s}".format(str(class_to_n_trials)))
    return SignalAndTarget(X, np.array(y))